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.AllocatableValue;
  32 import com.oracle.graal.api.code.CodeCacheProvider;
  33 import com.oracle.graal.api.code.DeoptimizationAction;
  34 import com.oracle.graal.api.code.RuntimeCallTarget;
  35 import com.oracle.graal.api.code.StackSlot;
  36 import com.oracle.graal.api.code.TargetDescription;
  37 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
  38 import com.oracle.graal.api.meta.Constant;
  39 import com.oracle.graal.api.meta.DeoptimizationReason;
  40 import com.oracle.graal.api.meta.Kind;
  41 import com.oracle.graal.api.meta.ResolvedJavaMethod;
  42 import com.oracle.graal.api.meta.Value;
  43 import com.oracle.graal.asm.NumUtil;
  44 import com.oracle.graal.compiler.gen.LIRGenerator;
  45 import com.oracle.graal.compiler.target.LIRGenLowerable;
  46 import com.oracle.graal.graph.GraalInternalError;
  47 import com.oracle.graal.lir.FrameMap;
  48 import com.oracle.graal.lir.LIR;
  49 import com.oracle.graal.lir.LIRFrameState;
  50 import com.oracle.graal.lir.LIRInstruction;
  51 import com.oracle.graal.lir.LIRValueUtil;
  52 import com.oracle.graal.lir.LabelRef;
  53 import com.oracle.graal.lir.StandardOp.JumpOp;
  54 import com.oracle.graal.lir.Variable;
  55 import com.oracle.graal.lir.ptx.PTXAddressValue;
  56 import com.oracle.graal.lir.ptx.PTXArithmetic.Op1Stack;
  57 import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Reg;
  58 import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Stack;
  59 import com.oracle.graal.lir.ptx.PTXArithmetic.ShiftOp;
  60 import com.oracle.graal.lir.ptx.PTXBitManipulationOp;
  61 import com.oracle.graal.lir.ptx.PTXCompare.CompareOp;
  62 import com.oracle.graal.lir.ptx.PTXControlFlow.BranchOp;
  63 import com.oracle.graal.lir.ptx.PTXControlFlow.CondMoveOp;
  64 import com.oracle.graal.lir.ptx.PTXControlFlow.FloatCondMoveOp;
  65 import com.oracle.graal.lir.ptx.PTXControlFlow.ReturnOp;
  66 import com.oracle.graal.lir.ptx.PTXControlFlow.SequentialSwitchOp;
  67 import com.oracle.graal.lir.ptx.PTXControlFlow.TableSwitchOp;
  68 import com.oracle.graal.lir.ptx.PTXMove.LoadOp;
  69 import com.oracle.graal.lir.ptx.PTXMove.MoveFromRegOp;
  70 import com.oracle.graal.lir.ptx.PTXMove.MoveToRegOp;
  71 import com.oracle.graal.lir.ptx.PTXMove.StoreOp;
  72 import com.oracle.graal.nodes.BreakpointNode;
  73 import com.oracle.graal.nodes.DirectCallTargetNode;
  74 import com.oracle.graal.nodes.IndirectCallTargetNode;
  75 import com.oracle.graal.nodes.SafepointNode;
  76 import com.oracle.graal.nodes.StructuredGraph;
  77 import com.oracle.graal.nodes.ValueNode;
  78 import com.oracle.graal.nodes.calc.Condition;
  79 import com.oracle.graal.nodes.calc.ConvertNode;
  80 import com.oracle.graal.nodes.java.CompareAndSwapNode;
  81 
  82 /**
  83  * This class implements the PTX specific portion of the LIR generator.
  84  */
  85 public class PTXLIRGenerator extends LIRGenerator {
  86 
  87     public static final Descriptor ARITHMETIC_FREM = new Descriptor("arithmeticFrem", false, float.class, float.class, float.class);
  88     public static final Descriptor ARITHMETIC_DREM = new Descriptor("arithmeticDrem", false, double.class, double.class, double.class);
  89 
  90     public static class PTXSpillMoveFactory implements LIR.SpillMoveFactory {
  91 
  92         @Override
  93         public LIRInstruction createMove(Value result, Value input) {
  94             throw new InternalError("NYI");
  95         }
  96     }
  97 
  98     public PTXLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) {
  99         super(graph, runtime, target, frameMap, method, lir);
 100         lir.spillMoveFactory = new PTXSpillMoveFactory();
 101     }
 102 
 103     @Override
 104     protected void emitNode(ValueNode node) {
 105         if (node instanceof LIRGenLowerable) {
 106             ((LIRGenLowerable) node).generate(this);
 107         } else {
 108             super.emitNode(node);
 109         }
 110     }
 111 
 112     @Override
 113     public boolean canStoreConstant(Constant c) {
 114         // Operand b must be in the .reg state space.
 115         return false;
 116     }
 117 
 118     @Override
 119     public boolean canInlineConstant(Constant c) {
 120         switch (c.getKind()) {
 121             case Long:
 122                 return NumUtil.isInt(c.asLong()) && !runtime.needsDataPatch(c);
 123             case Object:
 124                 return c.isNull();
 125             default:
 126                 return true;
 127         }
 128     }
 129 
 130     @Override
 131     public Variable emitMove(Value input) {
 132         Variable result = newVariable(input.getKind());
 133         emitMove(result, input);
 134         return result;
 135     }
 136 
 137     @Override
 138     public void emitMove(Value dst, Value src) {
 139         if (isRegister(src) || isStackSlot(dst)) {
 140             append(new MoveFromRegOp(dst, src));
 141         } else {
 142             append(new MoveToRegOp(dst, src));
 143         }
 144     }
 145 
 146     private PTXAddressValue prepareAddress(Kind kind, Value base, int displacement, Value index, int scale) {
 147         AllocatableValue baseRegister;
 148         long finalDisp = displacement;
 149         if (isConstant(base)) {
 150             if (asConstant(base).isNull()) {
 151                 baseRegister = AllocatableValue.UNUSED;
 152             } else if (asConstant(base).getKind() != Kind.Object) {
 153                 finalDisp += asConstant(base).asLong();
 154                 baseRegister = AllocatableValue.UNUSED;
 155             } else {
 156                 baseRegister = load(base);
 157             }
 158         } else if (base == Value.ILLEGAL) {
 159             baseRegister = AllocatableValue.UNUSED;
 160         } else {
 161             baseRegister = asAllocatable(base);
 162         }
 163 
 164         if (index != Value.ILLEGAL) {
 165             if (isConstant(index)) {
 166                 finalDisp += asConstant(index).asLong() * scale;
 167             } else {
 168                 Value indexRegister;
 169                 if (scale != 1) {
 170                     indexRegister = emitMul(index, Constant.forInt(scale));
 171                 } else {
 172                     indexRegister = index;
 173                 }
 174 
 175                 if (baseRegister == AllocatableValue.UNUSED) {
 176                     baseRegister = asAllocatable(indexRegister);
 177                 } else {
 178                     baseRegister = emitAdd(baseRegister, indexRegister);
 179                 }
 180             }
 181         }
 182 
 183         return new PTXAddressValue(kind, baseRegister, finalDisp);
 184     }
 185 
 186     @Override
 187     public Variable emitLoad(Kind kind, Value base, int displacement, Value index, int scale, boolean canTrap) {
 188         PTXAddressValue loadAddress = prepareAddress(kind, base, displacement, index, scale);
 189         Variable result = newVariable(loadAddress.getKind());
 190         append(new LoadOp(result, loadAddress, canTrap ? state() : null));
 191         return result;
 192     }
 193 
 194     @Override
 195     public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value inputVal, boolean canTrap) {
 196         PTXAddressValue storeAddress = prepareAddress(kind, base, displacement, index, scale);
 197         Variable input = load(inputVal);
 198         append(new StoreOp(storeAddress, input, canTrap ? state() : null));
 199     }
 200 
 201     @Override
 202     public Variable emitLea(Value base, int displacement, Value index, int scale) {
 203         throw new InternalError("NYI");
 204     }
 205 
 206     @Override
 207     public Variable emitLea(StackSlot address) {
 208         throw new InternalError("NYI");
 209     }
 210 
 211     @Override
 212     public void emitJump(LabelRef label) {
 213         append(new JumpOp(label));
 214     }
 215 
 216     @Override
 217     public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label) {
 218         switch (left.getKind().getStackKind()) {
 219             case Int:
 220                 append(new CompareOp(ICMP, cond, left, right));
 221                 append(new BranchOp(cond, label));
 222                 break;
 223             case Long:
 224                 append(new CompareOp(LCMP, cond, left, right));
 225                 append(new BranchOp(cond, label));
 226                 break;
 227             case Float:
 228                 append(new CompareOp(FCMP, cond, left, right));
 229                 append(new BranchOp(cond, label));
 230                 break;
 231             case Double:
 232                 append(new CompareOp(DCMP, cond, left, right));
 233                 append(new BranchOp(cond, label));
 234                 break;
 235             case Object:
 236                 append(new CompareOp(ACMP, cond, left, right));
 237                 append(new BranchOp(cond, label));
 238                 break;
 239             default:
 240                 System.err.println("missing: " + left.getKind());
 241                 throw GraalInternalError.shouldNotReachHere("" + left.getKind());
 242         }
 243     }
 244 
 245     @Override
 246     public void emitOverflowCheckBranch(LabelRef label, boolean negated) {
 247         throw new InternalError("NYI");
 248     }
 249 
 250     @Override
 251     public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label) {
 252         throw new InternalError("NYI");
 253     }
 254 
 255     @Override
 256     public Variable emitConditionalMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
 257         boolean mirrored = emitCompare(cond, left, right);
 258         Condition finalCondition = mirrored ? cond.mirror() : cond;
 259 
 260         Variable result = newVariable(trueValue.getKind());
 261         switch (left.getKind().getStackKind()) {
 262             case Int:
 263             case Long:
 264             case Object:
 265                 append(new CondMoveOp(result, finalCondition, load(trueValue), loadNonConst(falseValue)));
 266                 break;
 267             case Float:
 268             case Double:
 269                 append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue)));
 270                 break;
 271             default:
 272                 throw GraalInternalError.shouldNotReachHere("missing: " + left.getKind());
 273         }
 274         return result;
 275     }
 276 
 277     /**
 278      * This method emits the compare instruction, and may reorder the operands. It returns true if
 279      * it did so.
 280      * 
 281      * @param a the left operand of the comparison
 282      * @param b the right operand of the comparison
 283      * @return true if the left and right operands were switched, false otherwise
 284      */
 285     private boolean emitCompare(Condition cond, Value a, Value b) {
 286         Variable left;
 287         Value right;
 288         boolean mirrored;
 289         if (LIRValueUtil.isVariable(b)) {
 290             left = load(b);
 291             right = loadNonConst(a);
 292             mirrored = true;
 293         } else {
 294             left = load(a);
 295             right = loadNonConst(b);
 296             mirrored = false;
 297         }
 298         switch (left.getKind().getStackKind()) {
 299             case Int:
 300                 append(new CompareOp(ICMP, cond, left, right));
 301                 break;
 302             case Long:
 303                 append(new CompareOp(LCMP, cond, left, right));
 304                 break;
 305             case Object:
 306                 append(new CompareOp(ACMP, cond, left, right));
 307                 break;
 308             case Float:
 309                 append(new CompareOp(FCMP, cond, left, right));
 310                 break;
 311             case Double:
 312                 append(new CompareOp(DCMP, cond, left, right));
 313                 break;
 314             default:
 315                 throw GraalInternalError.shouldNotReachHere();
 316         }
 317         return mirrored;
 318     }
 319 
 320     @Override
 321     public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) {
 322         throw new InternalError("NYI");
 323     }
 324 
 325     @Override
 326     public Variable emitNegate(Value input) {
 327         Variable result = newVariable(input.getKind());
 328         switch (input.getKind()) {
 329             case Int:
 330                 append(new Op1Stack(INEG, result, input));
 331                 break;
 332             case Float:
 333                 append(new Op1Stack(FNEG, result, input));
 334                 break;
 335             case Double:
 336                 append(new Op1Stack(DNEG, result, input));
 337                 break;
 338             default:
 339                 throw GraalInternalError.shouldNotReachHere();
 340         }
 341         return result;
 342     }
 343 
 344     @Override
 345     public Variable emitAdd(Value a, Value b) {
 346         Variable result = newVariable(a.getKind());
 347         switch (a.getKind()) {
 348             case Int:
 349                 append(new Op2Stack(IADD, result, a, loadNonConst(b)));
 350                 break;
 351             case Long:
 352                 append(new Op2Stack(LADD, result, a, loadNonConst(b)));
 353                 break;
 354             case Float:
 355                 append(new Op2Stack(FADD, result, a, loadNonConst(b)));
 356                 break;
 357             case Double:
 358                 append(new Op2Stack(DADD, result, a, loadNonConst(b)));
 359                 break;
 360             default:
 361                 throw GraalInternalError.shouldNotReachHere();
 362         }
 363         return result;
 364     }
 365 
 366     @Override
 367     public Variable emitSub(Value a, Value b) {
 368         Variable result = newVariable(a.getKind());
 369         switch (a.getKind()) {
 370             case Int:
 371                 append(new Op2Stack(ISUB, result, a, loadNonConst(b)));
 372                 break;
 373             case Long:
 374                 append(new Op2Stack(LSUB, result, a, loadNonConst(b)));
 375                 break;
 376             case Float:
 377                 append(new Op2Stack(FSUB, result, a, loadNonConst(b)));
 378                 break;
 379             case Double:
 380                 append(new Op2Stack(DSUB, result, a, loadNonConst(b)));
 381                 break;
 382             default:
 383                 throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
 384         }
 385         return result;
 386     }
 387 
 388     @Override
 389     public Variable emitMul(Value a, Value b) {
 390         Variable result = newVariable(a.getKind());
 391         switch (a.getKind()) {
 392             case Int:
 393                 append(new Op2Reg(IMUL, result, a, loadNonConst(b)));
 394                 break;
 395             case Long:
 396                 append(new Op2Reg(LMUL, result, a, loadNonConst(b)));
 397                 break;
 398             case Float:
 399                 append(new Op2Stack(FMUL, result, a, loadNonConst(b)));
 400                 break;
 401             case Double:
 402                 append(new Op2Stack(DMUL, result, a, loadNonConst(b)));
 403                 break;
 404            default:
 405                 throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
 406         }
 407         return result;
 408     }
 409 
 410     @Override
 411     protected boolean peephole(ValueNode valueNode) {
 412         // No peephole optimizations for now
 413         return false;
 414     }
 415 
 416     @Override
 417     public Value emitDiv(Value a, Value b) {
 418         Variable result = newVariable(a.getKind());
 419         switch (a.getKind()) {
 420             case Int:
 421                 append(new Op2Reg(IDIV, result, a, loadNonConst(b)));
 422                 break;
 423             case Long:
 424                 append(new Op2Reg(LDIV, result, a, loadNonConst(b)));
 425                 break;
 426             case Float:
 427                 append(new Op2Stack(FDIV, result, a, loadNonConst(b)));
 428                 break;
 429             case Double:
 430                 append(new Op2Stack(DDIV, result, a, loadNonConst(b)));
 431                 break;
 432            default:
 433                 throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
 434         }
 435         return result;
 436     }
 437 
 438     @Override
 439     public Value emitRem(Value a, Value b) {
 440         Variable result = newVariable(a.getKind());
 441         switch (a.getKind()) {
 442             case Int:
 443                 append(new Op2Reg(IREM, result, a, loadNonConst(b)));
 444                 break;
 445             case Long:
 446                 append(new Op2Reg(LREM, result, a, loadNonConst(b)));
 447                 break;
 448             /*
 449              * not correct - these need to call the PTX double-precision remainder() function
 450             case Float: {
 451                 RuntimeCallTarget stub = runtime.lookupRuntimeCall(ARITHMETIC_FREM);
 452                 return emitCall(stub, stub.getCallingConvention(), false, a, b);
 453             }
 454             case Double: {
 455                 RuntimeCallTarget stub = runtime.lookupRuntimeCall(ARITHMETIC_DREM);
 456                 return emitCall(stub, stub.getCallingConvention(), false, a, b);
 457             }
 458             */
 459            default:
 460                 throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
 461         }
 462         return result;
 463     }
 464 
 465     @Override
 466     public Variable emitUDiv(Value a, Value b) {
 467         throw new InternalError("NYI");
 468     }
 469 
 470     @Override
 471     public Variable emitURem(Value a, Value b) {
 472         throw new InternalError("NYI");
 473     }
 474 
 475     @Override
 476     public Variable emitAnd(Value a, Value b) {
 477         Variable result = newVariable(a.getKind());
 478         switch (a.getKind()) {
 479             case Int:
 480                 append(new Op2Stack(IAND, result, a, loadNonConst(b)));
 481                 break;
 482             case Long:
 483                 append(new Op2Stack(LAND, result, a, loadNonConst(b)));
 484                 break;
 485 
 486             default:
 487                 throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
 488         }
 489         return result;
 490     }
 491 
 492     @Override
 493     public Variable emitOr(Value a, Value b) {
 494         Variable result = newVariable(a.getKind());
 495         switch (a.getKind()) {
 496             case Int:
 497                 append(new Op2Stack(IOR, result, a, loadNonConst(b)));
 498                 break;
 499             case Long:
 500                 append(new Op2Stack(LOR, result, a, loadNonConst(b)));
 501                 break;
 502             default:
 503                throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
 504         }
 505         return result;
 506     }
 507 
 508     @Override
 509     public Variable emitXor(Value a, Value b) {
 510         Variable result = newVariable(a.getKind());
 511         switch (a.getKind()) {
 512             case Int:
 513                 append(new Op2Stack(IXOR, result, a, loadNonConst(b)));
 514                 break;
 515             case Long:
 516                 append(new Op2Stack(LXOR, result, a, loadNonConst(b)));
 517                 break;
 518             default:
 519                 throw GraalInternalError.shouldNotReachHere();
 520         }
 521         return result;
 522      }
 523 
 524     @Override
 525     public Variable emitShl(Value a, Value b) {
 526         Variable result = newVariable(a.getKind());
 527         switch (a.getKind()) {
 528             case Int:
 529                 append(new Op2Stack(ISHL, result, a, loadNonConst(b)));
 530                 break;
 531             case Long:
 532                 append(new Op2Stack(LSHL, result, a, loadNonConst(b)));
 533                 break;
 534             default:
 535                 throw GraalInternalError.shouldNotReachHere();
 536         }
 537         return result;
 538     }
 539 
 540     @Override
 541     public Variable emitShr(Value a, Value b) {
 542         Variable result = newVariable(a.getKind());
 543         switch (a.getKind()) {
 544             case Int:
 545                 append(new Op2Stack(ISHR, result, a, loadNonConst(b)));
 546                 break;
 547             case Long:
 548                 append(new Op2Stack(LSHR, result, a, loadNonConst(b)));
 549                 break;
 550             default:
 551                 throw GraalInternalError.shouldNotReachHere();
 552         }
 553         return result;
 554     }
 555 
 556     @Override
 557     public Variable emitUShr(Value a, Value b) {
 558         Variable result = newVariable(a.getKind());
 559         switch (a.getKind()) {
 560             case Int:
 561                 append(new ShiftOp(IUSHR, result, a, b));
 562                 break;
 563             case Long:
 564                 append(new ShiftOp(LUSHR, result, a, b));
 565                 break;
 566             default:
 567                 GraalInternalError.shouldNotReachHere();
 568         }
 569         return result;
 570     }
 571 
 572     @Override
 573     public Variable emitConvert(ConvertNode.Op opcode, Value inputVal) {
 574         Variable input = load(inputVal);
 575         Variable result = newVariable(opcode.to);
 576         switch (opcode) {
 577             case I2L:
 578                 append(new Unary2Op(I2L, result, input));
 579                 break;
 580             case L2I:
 581                 append(new Unary1Op(L2I, result, input));
 582                 break;
 583             case I2B:
 584                 append(new Unary2Op(I2B, result, input));
 585                 break;
 586             case I2C:
 587                 append(new Unary1Op(I2C, result, input));
 588                 break;
 589             case I2S:
 590                 append(new Unary2Op(I2S, result, input));
 591                 break;
 592             case F2D:
 593                 append(new Unary2Op(F2D, result, input));
 594                 break;
 595             case D2F:
 596                 append(new Unary2Op(D2F, result, input));
 597                 break;
 598             case I2F:
 599                 append(new Unary2Op(I2F, result, input));
 600                 break;
 601             case I2D:
 602                 append(new Unary2Op(I2D, result, input));
 603                 break;
 604             case F2I:
 605                 append(new Unary2Op(F2I, result, input));
 606                 break;
 607             case D2I:
 608                 append(new Unary2Op(D2I, result, input));
 609                 break;
 610             case L2F:
 611                 append(new Unary2Op(L2F, result, input));
 612                 break;
 613             case L2D:
 614                 append(new Unary2Op(L2D, result, input));
 615                 break;
 616             case F2L:
 617                 append(new Unary2Op(F2L, result, input));
 618                 break;
 619             case D2L:
 620                 append(new Unary2Op(D2L, result, input));
 621                 break;
 622             case MOV_I2F:
 623                 append(new Unary2Op(MOV_I2F, result, input));
 624                 break;
 625             case MOV_L2D:
 626                 append(new Unary2Op(MOV_L2D, result, input));
 627                 break;
 628             case MOV_F2I:
 629                 append(new Unary2Op(MOV_F2I, result, input));
 630                 break;
 631             case MOV_D2L:
 632                 append(new Unary2Op(MOV_D2L, result, input));
 633                 break;
 634             case UNSIGNED_I2L:
 635                 // Instructions that move or generate 32-bit register values also set the upper 32
 636                 // bits of the register to zero.
 637                 // Consequently, there is no need for a special zero-extension move.
 638                 emitMove(result, input);
 639                 break;
 640             default:
 641                 throw GraalInternalError.shouldNotReachHere();
 642         }
 643         return result;
 644     }
 645 
 646     @Override
 647     public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason) {
 648         append(new ReturnOp(Value.ILLEGAL));
 649     }
 650 
 651     @Override
 652     public void emitMembar(int barriers) {
 653         throw new InternalError("NYI");
 654     }
 655 
 656     @Override
 657     protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
 658         throw new InternalError("NYI");
 659     }
 660 
 661     @Override
 662     protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
 663         throw new InternalError("NYI");
 664     }
 665 
 666     @Override
 667     protected void emitCall(RuntimeCallTarget callTarget, Value result, Value[] arguments, Value[] temps, LIRFrameState info) {
 668         throw new InternalError("NYI");
 669     }
 670 
 671     @Override
 672     public void emitBitCount(Variable result, Value value) {
 673         if (value.getKind().getStackKind() == Kind.Int) {
 674             append(new PTXBitManipulationOp(IPOPCNT, result, value));
 675         } else {
 676             append(new PTXBitManipulationOp(LPOPCNT, result, value));
 677         }
 678     }
 679 
 680     @Override
 681     public void emitBitScanForward(Variable result, Value value) {
 682         throw new InternalError("NYI");
 683     }
 684 
 685     @Override
 686     public void emitBitScanReverse(Variable result, Value value) {
 687         throw new InternalError("NYI");
 688     }
 689 
 690     @Override
 691     public void emitMathAbs(Variable result, Variable input) {
 692         throw new InternalError("NYI");
 693     }
 694 
 695     @Override
 696     public void emitMathSqrt(Variable result, Variable input) {
 697         throw new InternalError("NYI");
 698     }
 699 
 700     @Override
 701     public void emitMathLog(Variable result, Variable input, boolean base10) {
 702         throw new InternalError("NYI");
 703     }
 704 
 705     @Override
 706     public void emitMathCos(Variable result, Variable input) {
 707         throw new InternalError("NYI");
 708     }
 709 
 710     @Override
 711     public void emitMathSin(Variable result, Variable input) {
 712         throw new InternalError("NYI");
 713     }
 714 
 715     @Override
 716     public void emitMathTan(Variable result, Variable input) {
 717         throw new InternalError("NYI");
 718     }
 719 
 720     @Override
 721     public void emitByteSwap(Variable result, Value input) {
 722         throw new InternalError("NYI");
 723     }
 724 
 725     @Override
 726     protected void emitReturn(Value input) {
 727         append(new ReturnOp(input));
 728     }
 729 
 730     @Override
 731     protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) {
 732         // Making a copy of the switch value is necessary because jump table destroys the input
 733         // value
 734         if (key.getKind() == Kind.Int || key.getKind() == Kind.Long) {
 735             append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, Value.ILLEGAL));
 736         } else {
 737             assert key.getKind() == Kind.Object : key.getKind();
 738             append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, newVariable(Kind.Object)));
 739         }
 740     }
 741 
 742     @Override
 743     protected void emitSwitchRanges(int[] lowKeys, int[] highKeys, LabelRef[] targets, LabelRef defaultTarget, Value key) {
 744         throw new InternalError("NYI");
 745     }
 746 
 747     @Override
 748     protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) {
 749         // Making a copy of the switch value is necessary because jump table destroys the input
 750         // value
 751         Variable tmp = emitMove(key);
 752         append(new TableSwitchOp(lowKey, defaultTarget, targets, tmp, newVariable(target.wordKind)));
 753     }
 754 
 755     @Override
 756     public void visitCompareAndSwap(CompareAndSwapNode node) {
 757         throw new InternalError("NYI");
 758     }
 759 
 760     @Override
 761     public void visitBreakpointNode(BreakpointNode node) {
 762         throw new InternalError("NYI");
 763     }
 764 
 765     @Override
 766     public void visitSafepointNode(SafepointNode i) {
 767         // LIRFrameState info = state();
 768         // append(new PTXSafepointOp(info, runtime().config, this));
 769         throw new InternalError("NYI");
 770     }
 771 
 772     @Override
 773     public void emitUnwind(Value operand) {
 774         throw new InternalError("NYI");
 775     }
 776 
 777     @Override
 778     public void emitNullCheck(ValueNode v) {
 779         throw new InternalError("NYI");
 780     }
 781 }