< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java

Print this page




   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 org.graalvm.compiler.lir.amd64;
  24 


  25 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.CONST;
  26 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
  27 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
  28 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
  29 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
  30 import static jdk.vm.ci.code.ValueUtil.asRegister;
  31 import static jdk.vm.ci.code.ValueUtil.isRegister;
  32 
  33 import org.graalvm.compiler.asm.Label;
  34 import org.graalvm.compiler.core.common.NumUtil;
  35 import org.graalvm.compiler.asm.amd64.AMD64Address;
  36 import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
  37 import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
  38 import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
  39 import org.graalvm.compiler.code.CompilationResult.JumpTable;

  40 import org.graalvm.compiler.core.common.calc.Condition;
  41 import org.graalvm.compiler.debug.GraalError;
  42 import org.graalvm.compiler.lir.LIRInstructionClass;
  43 import org.graalvm.compiler.lir.LabelRef;
  44 import org.graalvm.compiler.lir.Opcode;
  45 import org.graalvm.compiler.lir.StandardOp;
  46 import org.graalvm.compiler.lir.StandardOp.BlockEndOp;
  47 import org.graalvm.compiler.lir.SwitchStrategy;
  48 import org.graalvm.compiler.lir.SwitchStrategy.BaseSwitchClosure;
  49 import org.graalvm.compiler.lir.Variable;
  50 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
  51 
  52 import jdk.vm.ci.amd64.AMD64;
  53 import jdk.vm.ci.amd64.AMD64.CPUFeature;
  54 import jdk.vm.ci.amd64.AMD64Kind;
  55 import jdk.vm.ci.code.Register;
  56 import jdk.vm.ci.meta.AllocatableValue;
  57 import jdk.vm.ci.meta.Constant;
  58 import jdk.vm.ci.meta.JavaConstant;
  59 import jdk.vm.ci.meta.Value;


 295             for (LabelRef target : targets) {
 296                 Label label = target.label();
 297                 int offsetToJumpTableBase = masm.position() - jumpTablePos;
 298                 if (label.isBound()) {
 299                     int imm32 = label.position() - jumpTablePos;
 300                     masm.emitInt(imm32);
 301                 } else {
 302                     label.addPatchAt(masm.position());
 303 
 304                     masm.emitByte(0); // pseudo-opcode for jump table entry
 305                     masm.emitShort(offsetToJumpTableBase);
 306                     masm.emitByte(0); // padding to make jump table entry 4 bytes wide
 307                 }
 308             }
 309 
 310             JumpTable jt = new JumpTable(jumpTablePos, lowKey, highKey, 4);
 311             crb.compilationResult.addAnnotation(jt);
 312         }
 313     }
 314 




































 315     @Opcode("CMOVE")
 316     public static final class CondMoveOp extends AMD64LIRInstruction {
 317         public static final LIRInstructionClass<CondMoveOp> TYPE = LIRInstructionClass.create(CondMoveOp.class);
 318         @Def({REG, HINT}) protected Value result;
 319         @Alive({REG}) protected Value trueValue;
 320         @Use({REG, STACK, CONST}) protected Value falseValue;
 321         private final ConditionFlag condition;
 322 
 323         public CondMoveOp(Variable result, Condition condition, AllocatableValue trueValue, Value falseValue) {
 324             super(TYPE);
 325             this.result = result;
 326             this.condition = intCond(condition);
 327             this.trueValue = trueValue;
 328             this.falseValue = falseValue;
 329         }
 330 
 331         @Override
 332         public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
 333             cmove(crb, masm, result, false, condition, false, trueValue, falseValue);
 334         }


 401                 default:
 402                     throw GraalError.shouldNotReachHere();
 403             }
 404         } else {
 405             AMD64Address addr = (AMD64Address) crb.asAddress(other);
 406             switch ((AMD64Kind) other.getPlatformKind()) {
 407                 case BYTE:
 408                 case WORD:
 409                 case DWORD:
 410                     masm.cmovl(cond, asRegister(result), addr);
 411                     break;
 412                 case QWORD:
 413                     masm.cmovq(cond, asRegister(result), addr);
 414                     break;
 415                 default:
 416                     throw GraalError.shouldNotReachHere();
 417             }
 418         }
 419     }
 420 















 421     private static ConditionFlag intCond(Condition cond) {
 422         switch (cond) {
 423             case EQ:
 424                 return ConditionFlag.Equal;
 425             case NE:
 426                 return ConditionFlag.NotEqual;
 427             case LT:
 428                 return ConditionFlag.Less;
 429             case LE:
 430                 return ConditionFlag.LessEqual;
 431             case GE:
 432                 return ConditionFlag.GreaterEqual;
 433             case GT:
 434                 return ConditionFlag.Greater;
 435             case BE:
 436                 return ConditionFlag.BelowEqual;
 437             case AE:
 438                 return ConditionFlag.AboveEqual;
 439             case AT:
 440                 return ConditionFlag.Above;


 445         }
 446     }
 447 
 448     private static ConditionFlag floatCond(Condition cond) {
 449         switch (cond) {
 450             case EQ:
 451                 return ConditionFlag.Equal;
 452             case NE:
 453                 return ConditionFlag.NotEqual;
 454             case LT:
 455                 return ConditionFlag.Below;
 456             case LE:
 457                 return ConditionFlag.BelowEqual;
 458             case GE:
 459                 return ConditionFlag.AboveEqual;
 460             case GT:
 461                 return ConditionFlag.Above;
 462             default:
 463                 throw GraalError.shouldNotReachHere();
 464         }




 465     }
 466 
 467     private static boolean trueOnUnordered(ConditionFlag condition) {
 468         switch (condition) {
 469             case AboveEqual:
 470             case NotEqual:
 471             case Above:
 472             case Less:
 473             case Overflow:
 474                 return false;
 475             case Equal:
 476             case BelowEqual:
 477             case Below:
 478             case GreaterEqual:
 479             case NoOverflow:
 480                 return true;
 481             default:
 482                 throw GraalError.shouldNotReachHere();
 483         }
 484     }


   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 org.graalvm.compiler.lir.amd64;
  24 
  25 import static jdk.vm.ci.code.ValueUtil.asRegister;
  26 import static jdk.vm.ci.code.ValueUtil.isRegister;
  27 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.CONST;
  28 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
  29 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
  30 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
  31 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;


  32 
  33 import org.graalvm.compiler.asm.Label;

  34 import org.graalvm.compiler.asm.amd64.AMD64Address;
  35 import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
  36 import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
  37 import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
  38 import org.graalvm.compiler.code.CompilationResult.JumpTable;
  39 import org.graalvm.compiler.core.common.NumUtil;
  40 import org.graalvm.compiler.core.common.calc.Condition;
  41 import org.graalvm.compiler.debug.GraalError;
  42 import org.graalvm.compiler.lir.LIRInstructionClass;
  43 import org.graalvm.compiler.lir.LabelRef;
  44 import org.graalvm.compiler.lir.Opcode;
  45 import org.graalvm.compiler.lir.StandardOp;
  46 import org.graalvm.compiler.lir.StandardOp.BlockEndOp;
  47 import org.graalvm.compiler.lir.SwitchStrategy;
  48 import org.graalvm.compiler.lir.SwitchStrategy.BaseSwitchClosure;
  49 import org.graalvm.compiler.lir.Variable;
  50 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
  51 
  52 import jdk.vm.ci.amd64.AMD64;
  53 import jdk.vm.ci.amd64.AMD64.CPUFeature;
  54 import jdk.vm.ci.amd64.AMD64Kind;
  55 import jdk.vm.ci.code.Register;
  56 import jdk.vm.ci.meta.AllocatableValue;
  57 import jdk.vm.ci.meta.Constant;
  58 import jdk.vm.ci.meta.JavaConstant;
  59 import jdk.vm.ci.meta.Value;


 295             for (LabelRef target : targets) {
 296                 Label label = target.label();
 297                 int offsetToJumpTableBase = masm.position() - jumpTablePos;
 298                 if (label.isBound()) {
 299                     int imm32 = label.position() - jumpTablePos;
 300                     masm.emitInt(imm32);
 301                 } else {
 302                     label.addPatchAt(masm.position());
 303 
 304                     masm.emitByte(0); // pseudo-opcode for jump table entry
 305                     masm.emitShort(offsetToJumpTableBase);
 306                     masm.emitByte(0); // padding to make jump table entry 4 bytes wide
 307                 }
 308             }
 309 
 310             JumpTable jt = new JumpTable(jumpTablePos, lowKey, highKey, 4);
 311             crb.compilationResult.addAnnotation(jt);
 312         }
 313     }
 314 
 315     @Opcode("SETcc")
 316     public static final class CondSetOp extends AMD64LIRInstruction {
 317         public static final LIRInstructionClass<CondSetOp> TYPE = LIRInstructionClass.create(CondSetOp.class);
 318         @Def({REG, HINT}) protected Value result;
 319         private final ConditionFlag condition;
 320 
 321         public CondSetOp(Variable result, Condition condition) {
 322             super(TYPE);
 323             this.result = result;
 324             this.condition = intCond(condition);
 325         }
 326 
 327         @Override
 328         public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
 329             setcc(masm, result, condition);
 330         }
 331     }
 332 
 333     @Opcode("SETcc")
 334     public static final class FloatCondSetOp extends AMD64LIRInstruction {
 335         public static final LIRInstructionClass<FloatCondSetOp> TYPE = LIRInstructionClass.create(FloatCondSetOp.class);
 336         @Def({REG, HINT}) protected Value result;
 337         private final ConditionFlag condition;
 338 
 339         public FloatCondSetOp(Variable result, Condition condition) {
 340             super(TYPE);
 341             this.result = result;
 342             this.condition = floatCond(condition);
 343         }
 344 
 345         @Override
 346         public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
 347             setcc(masm, result, condition);
 348         }
 349     }
 350 
 351     @Opcode("CMOVE")
 352     public static final class CondMoveOp extends AMD64LIRInstruction {
 353         public static final LIRInstructionClass<CondMoveOp> TYPE = LIRInstructionClass.create(CondMoveOp.class);
 354         @Def({REG, HINT}) protected Value result;
 355         @Alive({REG}) protected Value trueValue;
 356         @Use({REG, STACK, CONST}) protected Value falseValue;
 357         private final ConditionFlag condition;
 358 
 359         public CondMoveOp(Variable result, Condition condition, AllocatableValue trueValue, Value falseValue) {
 360             super(TYPE);
 361             this.result = result;
 362             this.condition = intCond(condition);
 363             this.trueValue = trueValue;
 364             this.falseValue = falseValue;
 365         }
 366 
 367         @Override
 368         public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
 369             cmove(crb, masm, result, false, condition, false, trueValue, falseValue);
 370         }


 437                 default:
 438                     throw GraalError.shouldNotReachHere();
 439             }
 440         } else {
 441             AMD64Address addr = (AMD64Address) crb.asAddress(other);
 442             switch ((AMD64Kind) other.getPlatformKind()) {
 443                 case BYTE:
 444                 case WORD:
 445                 case DWORD:
 446                     masm.cmovl(cond, asRegister(result), addr);
 447                     break;
 448                 case QWORD:
 449                     masm.cmovq(cond, asRegister(result), addr);
 450                     break;
 451                 default:
 452                     throw GraalError.shouldNotReachHere();
 453             }
 454         }
 455     }
 456 
 457     private static void setcc(AMD64MacroAssembler masm, Value result, ConditionFlag cond) {
 458         switch ((AMD64Kind) result.getPlatformKind()) {
 459             case BYTE:
 460             case WORD:
 461             case DWORD:
 462                 masm.setl(cond, asRegister(result));
 463                 break;
 464             case QWORD:
 465                 masm.setq(cond, asRegister(result));
 466                 break;
 467             default:
 468                 throw GraalError.shouldNotReachHere();
 469         }
 470     }
 471 
 472     private static ConditionFlag intCond(Condition cond) {
 473         switch (cond) {
 474             case EQ:
 475                 return ConditionFlag.Equal;
 476             case NE:
 477                 return ConditionFlag.NotEqual;
 478             case LT:
 479                 return ConditionFlag.Less;
 480             case LE:
 481                 return ConditionFlag.LessEqual;
 482             case GE:
 483                 return ConditionFlag.GreaterEqual;
 484             case GT:
 485                 return ConditionFlag.Greater;
 486             case BE:
 487                 return ConditionFlag.BelowEqual;
 488             case AE:
 489                 return ConditionFlag.AboveEqual;
 490             case AT:
 491                 return ConditionFlag.Above;


 496         }
 497     }
 498 
 499     private static ConditionFlag floatCond(Condition cond) {
 500         switch (cond) {
 501             case EQ:
 502                 return ConditionFlag.Equal;
 503             case NE:
 504                 return ConditionFlag.NotEqual;
 505             case LT:
 506                 return ConditionFlag.Below;
 507             case LE:
 508                 return ConditionFlag.BelowEqual;
 509             case GE:
 510                 return ConditionFlag.AboveEqual;
 511             case GT:
 512                 return ConditionFlag.Above;
 513             default:
 514                 throw GraalError.shouldNotReachHere();
 515         }
 516     }
 517 
 518     public static boolean trueOnUnordered(Condition condition) {
 519         return trueOnUnordered(floatCond(condition));
 520     }
 521 
 522     private static boolean trueOnUnordered(ConditionFlag condition) {
 523         switch (condition) {
 524             case AboveEqual:
 525             case NotEqual:
 526             case Above:
 527             case Less:
 528             case Overflow:
 529                 return false;
 530             case Equal:
 531             case BelowEqual:
 532             case Below:
 533             case GreaterEqual:
 534             case NoOverflow:
 535                 return true;
 536             default:
 537                 throw GraalError.shouldNotReachHere();
 538         }
 539     }
< prev index next >