1 /* 2 * Copyright (c) 2011, 2018, 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 25 package org.graalvm.compiler.lir.amd64; 26 27 import static jdk.vm.ci.code.ValueUtil.asRegister; 28 import static jdk.vm.ci.code.ValueUtil.isRegister; 29 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.CONST; 30 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; 31 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; 32 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; 33 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; 34 35 import org.graalvm.compiler.asm.Label; 36 import org.graalvm.compiler.asm.amd64.AMD64Address; 37 import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; 38 import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag; 39 import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; 40 import org.graalvm.compiler.code.CompilationResult.JumpTable; 41 import org.graalvm.compiler.core.common.NumUtil; 42 import org.graalvm.compiler.core.common.calc.Condition; 43 import org.graalvm.compiler.debug.GraalError; 44 import org.graalvm.compiler.lir.LIRInstructionClass; 45 import org.graalvm.compiler.lir.LabelRef; 46 import org.graalvm.compiler.lir.Opcode; 47 import org.graalvm.compiler.lir.StandardOp; 48 import org.graalvm.compiler.lir.StandardOp.BlockEndOp; 49 import org.graalvm.compiler.lir.SwitchStrategy; 50 import org.graalvm.compiler.lir.SwitchStrategy.BaseSwitchClosure; 51 import org.graalvm.compiler.lir.Variable; 52 import org.graalvm.compiler.lir.asm.CompilationResultBuilder; 53 54 import jdk.vm.ci.amd64.AMD64; 55 import jdk.vm.ci.amd64.AMD64.CPUFeature; 56 import jdk.vm.ci.amd64.AMD64Kind; 57 import jdk.vm.ci.code.Register; 58 import jdk.vm.ci.meta.AllocatableValue; 59 import jdk.vm.ci.meta.Constant; 60 import jdk.vm.ci.meta.JavaConstant; 61 import jdk.vm.ci.meta.Value; 62 63 public class AMD64ControlFlow { 64 65 public static final class ReturnOp extends AMD64BlockEndOp implements BlockEndOp { 66 public static final LIRInstructionClass<ReturnOp> TYPE = LIRInstructionClass.create(ReturnOp.class); 67 @Use({REG, ILLEGAL}) protected Value x; 68 ReturnOp(Value x)69 public ReturnOp(Value x) { 70 super(TYPE); 71 this.x = x; 72 } 73 74 @Override emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm)75 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 76 crb.frameContext.leave(crb); 77 /* 78 * We potentially return to the interpreter, and that's an AVX-SSE transition. The only 79 * live value at this point should be the return value in either rax, or in xmm0 with 80 * the upper half of the register unused, so we don't destroy any value here. 81 */ 82 if (masm.supports(CPUFeature.AVX)) { 83 masm.vzeroupper(); 84 } 85 masm.ret(0); 86 } 87 } 88 89 public static class BranchOp extends AMD64BlockEndOp implements StandardOp.BranchOp { 90 public static final LIRInstructionClass<BranchOp> TYPE = LIRInstructionClass.create(BranchOp.class); 91 protected final ConditionFlag condition; 92 protected final LabelRef trueDestination; 93 protected final LabelRef falseDestination; 94 95 private final double trueDestinationProbability; 96 BranchOp(Condition condition, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability)97 public BranchOp(Condition condition, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) { 98 this(intCond(condition), trueDestination, falseDestination, trueDestinationProbability); 99 } 100 BranchOp(ConditionFlag condition, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability)101 public BranchOp(ConditionFlag condition, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) { 102 this(TYPE, condition, trueDestination, falseDestination, trueDestinationProbability); 103 } 104 BranchOp(LIRInstructionClass<? extends BranchOp> c, ConditionFlag condition, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability)105 protected BranchOp(LIRInstructionClass<? extends BranchOp> c, ConditionFlag condition, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) { 106 super(c); 107 this.condition = condition; 108 this.trueDestination = trueDestination; 109 this.falseDestination = falseDestination; 110 this.trueDestinationProbability = trueDestinationProbability; 111 } 112 113 @Override emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm)114 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 115 boolean isNegated = false; 116 int jccPos = masm.position(); 117 /* 118 * The strategy for emitting jumps is: If either trueDestination or falseDestination is 119 * the successor block, assume the block scheduler did the correct thing and jcc to the 120 * other. Otherwise, we need a jcc followed by a jmp. Use the branch probability to make 121 * sure it is more likely to branch on the jcc (= less likely to execute both the jcc 122 * and the jmp instead of just the jcc). In the case of loops, that means the jcc is the 123 * back-edge. 124 */ 125 if (crb.isSuccessorEdge(trueDestination)) { 126 jcc(masm, true, falseDestination); 127 isNegated = true; 128 } else if (crb.isSuccessorEdge(falseDestination)) { 129 jcc(masm, false, trueDestination); 130 } else if (trueDestinationProbability < 0.5) { 131 jcc(masm, true, falseDestination); 132 masm.jmp(trueDestination.label()); 133 isNegated = true; 134 } else { 135 jcc(masm, false, trueDestination); 136 masm.jmp(falseDestination.label()); 137 } 138 crb.recordBranch(jccPos, isNegated); 139 } 140 jcc(AMD64MacroAssembler masm, boolean negate, LabelRef target)141 protected void jcc(AMD64MacroAssembler masm, boolean negate, LabelRef target) { 142 masm.jcc(negate ? condition.negate() : condition, target.label()); 143 } 144 } 145 146 public static final class FloatBranchOp extends BranchOp { 147 public static final LIRInstructionClass<FloatBranchOp> TYPE = LIRInstructionClass.create(FloatBranchOp.class); 148 protected boolean unorderedIsTrue; 149 FloatBranchOp(Condition condition, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability)150 public FloatBranchOp(Condition condition, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) { 151 super(TYPE, floatCond(condition), trueDestination, falseDestination, trueDestinationProbability); 152 this.unorderedIsTrue = unorderedIsTrue; 153 } 154 155 @Override jcc(AMD64MacroAssembler masm, boolean negate, LabelRef target)156 protected void jcc(AMD64MacroAssembler masm, boolean negate, LabelRef target) { 157 floatJcc(masm, negate ? condition.negate() : condition, negate ? !unorderedIsTrue : unorderedIsTrue, target.label()); 158 } 159 } 160 161 public static class StrategySwitchOp extends AMD64BlockEndOp { 162 public static final LIRInstructionClass<StrategySwitchOp> TYPE = LIRInstructionClass.create(StrategySwitchOp.class); 163 protected final Constant[] keyConstants; 164 private final LabelRef[] keyTargets; 165 private LabelRef defaultTarget; 166 @Alive({REG}) protected Value key; 167 @Temp({REG, ILLEGAL}) protected Value scratch; 168 protected final SwitchStrategy strategy; 169 StrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch)170 public StrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) { 171 this(TYPE, strategy, keyTargets, defaultTarget, key, scratch); 172 } 173 StrategySwitchOp(LIRInstructionClass<? extends StrategySwitchOp> c, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch)174 protected StrategySwitchOp(LIRInstructionClass<? extends StrategySwitchOp> c, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) { 175 super(c); 176 this.strategy = strategy; 177 this.keyConstants = strategy.getKeyConstants(); 178 this.keyTargets = keyTargets; 179 this.defaultTarget = defaultTarget; 180 this.key = key; 181 this.scratch = scratch; 182 assert keyConstants.length == keyTargets.length; 183 assert keyConstants.length == strategy.keyProbabilities.length; 184 } 185 186 @Override emitCode(final CompilationResultBuilder crb, final AMD64MacroAssembler masm)187 public void emitCode(final CompilationResultBuilder crb, final AMD64MacroAssembler masm) { 188 strategy.run(new SwitchClosure(asRegister(key), crb, masm)); 189 } 190 191 public class SwitchClosure extends BaseSwitchClosure { 192 193 protected final Register keyRegister; 194 protected final CompilationResultBuilder crb; 195 protected final AMD64MacroAssembler masm; 196 SwitchClosure(Register keyRegister, CompilationResultBuilder crb, AMD64MacroAssembler masm)197 protected SwitchClosure(Register keyRegister, CompilationResultBuilder crb, AMD64MacroAssembler masm) { 198 super(crb, masm, keyTargets, defaultTarget); 199 this.keyRegister = keyRegister; 200 this.crb = crb; 201 this.masm = masm; 202 } 203 emitComparison(Constant c)204 protected void emitComparison(Constant c) { 205 JavaConstant jc = (JavaConstant) c; 206 switch (jc.getJavaKind()) { 207 case Int: 208 long lc = jc.asLong(); 209 assert NumUtil.isInt(lc); 210 masm.cmpl(keyRegister, (int) lc); 211 break; 212 case Long: 213 masm.cmpq(keyRegister, (AMD64Address) crb.asLongConstRef(jc)); 214 break; 215 case Object: 216 AMD64Move.const2reg(crb, masm, asRegister(scratch), jc); 217 masm.cmpptr(keyRegister, asRegister(scratch)); 218 break; 219 default: 220 throw new GraalError("switch only supported for int, long and object"); 221 } 222 } 223 224 @Override conditionalJump(int index, Condition condition, Label target)225 protected void conditionalJump(int index, Condition condition, Label target) { 226 emitComparison(keyConstants[index]); 227 masm.jcc(intCond(condition), target); 228 } 229 } 230 } 231 232 public static final class TableSwitchOp extends AMD64BlockEndOp { 233 public static final LIRInstructionClass<TableSwitchOp> TYPE = LIRInstructionClass.create(TableSwitchOp.class); 234 private final int lowKey; 235 private final LabelRef defaultTarget; 236 private final LabelRef[] targets; 237 @Use protected Value index; 238 @Temp({REG, HINT}) protected Value idxScratch; 239 @Temp protected Value scratch; 240 TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Value index, Variable scratch, Variable idxScratch)241 public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Value index, Variable scratch, Variable idxScratch) { 242 super(TYPE); 243 this.lowKey = lowKey; 244 this.defaultTarget = defaultTarget; 245 this.targets = targets; 246 this.index = index; 247 this.scratch = scratch; 248 this.idxScratch = idxScratch; 249 } 250 251 @Override emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm)252 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 253 Register indexReg = asRegister(index, AMD64Kind.DWORD); 254 Register idxScratchReg = asRegister(idxScratch, AMD64Kind.DWORD); 255 Register scratchReg = asRegister(scratch, AMD64Kind.QWORD); 256 257 if (!indexReg.equals(idxScratchReg)) { 258 masm.movl(idxScratchReg, indexReg); 259 } 260 261 // Compare index against jump table bounds 262 int highKey = lowKey + targets.length - 1; 263 if (lowKey != 0) { 264 // subtract the low value from the switch value 265 masm.subl(idxScratchReg, lowKey); 266 masm.cmpl(idxScratchReg, highKey - lowKey); 267 } else { 268 masm.cmpl(idxScratchReg, highKey); 269 } 270 271 // Jump to default target if index is not within the jump table 272 if (defaultTarget != null) { 273 masm.jcc(ConditionFlag.Above, defaultTarget.label()); 274 } 275 276 // Set scratch to address of jump table 277 masm.leaq(scratchReg, new AMD64Address(AMD64.rip, 0)); 278 final int afterLea = masm.position(); 279 280 // Load jump table entry into scratch and jump to it 281 masm.movslq(idxScratchReg, new AMD64Address(scratchReg, idxScratchReg, Scale.Times4, 0)); 282 masm.addq(scratchReg, idxScratchReg); 283 masm.jmp(scratchReg); 284 285 // Inserting padding so that jump table address is 4-byte aligned 286 if ((masm.position() & 0x3) != 0) { 287 masm.nop(4 - (masm.position() & 0x3)); 288 } 289 290 // Patch LEA instruction above now that we know the position of the jump table 291 // TODO this is ugly and should be done differently 292 final int jumpTablePos = masm.position(); 293 final int leaDisplacementPosition = afterLea - 4; 294 masm.emitInt(jumpTablePos - afterLea, leaDisplacementPosition); 295 296 // Emit jump table entries 297 for (LabelRef target : targets) { 298 Label label = target.label(); 299 int offsetToJumpTableBase = masm.position() - jumpTablePos; 300 if (label.isBound()) { 301 int imm32 = label.position() - jumpTablePos; 302 masm.emitInt(imm32); 303 } else { 304 label.addPatchAt(masm.position()); 305 306 masm.emitByte(0); // pseudo-opcode for jump table entry 307 masm.emitShort(offsetToJumpTableBase); 308 masm.emitByte(0); // padding to make jump table entry 4 bytes wide 309 } 310 } 311 312 JumpTable jt = new JumpTable(jumpTablePos, lowKey, highKey, 4); 313 crb.compilationResult.addAnnotation(jt); 314 } 315 } 316 317 @Opcode("SETcc") 318 public static final class CondSetOp extends AMD64LIRInstruction { 319 public static final LIRInstructionClass<CondSetOp> TYPE = LIRInstructionClass.create(CondSetOp.class); 320 @Def({REG, HINT}) protected Value result; 321 private final ConditionFlag condition; 322 CondSetOp(Variable result, Condition condition)323 public CondSetOp(Variable result, Condition condition) { 324 super(TYPE); 325 this.result = result; 326 this.condition = intCond(condition); 327 } 328 329 @Override emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm)330 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 331 setcc(masm, result, condition); 332 } 333 } 334 335 @Opcode("SETcc") 336 public static final class FloatCondSetOp extends AMD64LIRInstruction { 337 public static final LIRInstructionClass<FloatCondSetOp> TYPE = LIRInstructionClass.create(FloatCondSetOp.class); 338 @Def({REG, HINT}) protected Value result; 339 private final ConditionFlag condition; 340 FloatCondSetOp(Variable result, Condition condition)341 public FloatCondSetOp(Variable result, Condition condition) { 342 super(TYPE); 343 this.result = result; 344 this.condition = floatCond(condition); 345 } 346 347 @Override emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm)348 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 349 setcc(masm, result, condition); 350 } 351 } 352 353 @Opcode("CMOVE") 354 public static final class CondMoveOp extends AMD64LIRInstruction { 355 public static final LIRInstructionClass<CondMoveOp> TYPE = LIRInstructionClass.create(CondMoveOp.class); 356 @Def({REG, HINT}) protected Value result; 357 @Alive({REG}) protected Value trueValue; 358 @Use({REG, STACK, CONST}) protected Value falseValue; 359 private final ConditionFlag condition; 360 CondMoveOp(Variable result, Condition condition, AllocatableValue trueValue, Value falseValue)361 public CondMoveOp(Variable result, Condition condition, AllocatableValue trueValue, Value falseValue) { 362 super(TYPE); 363 this.result = result; 364 this.condition = intCond(condition); 365 this.trueValue = trueValue; 366 this.falseValue = falseValue; 367 } 368 369 @Override emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm)370 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 371 cmove(crb, masm, result, false, condition, false, trueValue, falseValue); 372 } 373 } 374 375 @Opcode("CMOVE") 376 public static final class FloatCondMoveOp extends AMD64LIRInstruction { 377 public static final LIRInstructionClass<FloatCondMoveOp> TYPE = LIRInstructionClass.create(FloatCondMoveOp.class); 378 @Def({REG}) protected Value result; 379 @Alive({REG}) protected Value trueValue; 380 @Alive({REG}) protected Value falseValue; 381 private final ConditionFlag condition; 382 private final boolean unorderedIsTrue; 383 FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue)384 public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) { 385 super(TYPE); 386 this.result = result; 387 this.condition = floatCond(condition); 388 this.unorderedIsTrue = unorderedIsTrue; 389 this.trueValue = trueValue; 390 this.falseValue = falseValue; 391 } 392 393 @Override emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm)394 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 395 cmove(crb, masm, result, true, condition, unorderedIsTrue, trueValue, falseValue); 396 } 397 } 398 floatJcc(AMD64MacroAssembler masm, ConditionFlag condition, boolean unorderedIsTrue, Label label)399 private static void floatJcc(AMD64MacroAssembler masm, ConditionFlag condition, boolean unorderedIsTrue, Label label) { 400 Label endLabel = new Label(); 401 if (unorderedIsTrue && !trueOnUnordered(condition)) { 402 masm.jcc(ConditionFlag.Parity, label); 403 } else if (!unorderedIsTrue && trueOnUnordered(condition)) { 404 masm.jccb(ConditionFlag.Parity, endLabel); 405 } 406 masm.jcc(condition, label); 407 masm.bind(endLabel); 408 } 409 cmove(CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, boolean isFloat, ConditionFlag condition, boolean unorderedIsTrue, Value trueValue, Value falseValue)410 private static void cmove(CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, boolean isFloat, ConditionFlag condition, boolean unorderedIsTrue, Value trueValue, 411 Value falseValue) { 412 // check that we don't overwrite an input operand before it is used. 413 assert !result.equals(trueValue); 414 415 AMD64Move.move(crb, masm, result, falseValue); 416 cmove(crb, masm, result, condition, trueValue); 417 418 if (isFloat) { 419 if (unorderedIsTrue && !trueOnUnordered(condition)) { 420 cmove(crb, masm, result, ConditionFlag.Parity, trueValue); 421 } else if (!unorderedIsTrue && trueOnUnordered(condition)) { 422 cmove(crb, masm, result, ConditionFlag.Parity, falseValue); 423 } 424 } 425 } 426 cmove(CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, ConditionFlag cond, Value other)427 private static void cmove(CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, ConditionFlag cond, Value other) { 428 if (isRegister(other)) { 429 assert !asRegister(other).equals(asRegister(result)) : "other already overwritten by previous move"; 430 switch ((AMD64Kind) other.getPlatformKind()) { 431 case BYTE: 432 case WORD: 433 case DWORD: 434 masm.cmovl(cond, asRegister(result), asRegister(other)); 435 break; 436 case QWORD: 437 masm.cmovq(cond, asRegister(result), asRegister(other)); 438 break; 439 default: 440 throw GraalError.shouldNotReachHere(); 441 } 442 } else { 443 AMD64Address addr = (AMD64Address) crb.asAddress(other); 444 switch ((AMD64Kind) other.getPlatformKind()) { 445 case BYTE: 446 case WORD: 447 case DWORD: 448 masm.cmovl(cond, asRegister(result), addr); 449 break; 450 case QWORD: 451 masm.cmovq(cond, asRegister(result), addr); 452 break; 453 default: 454 throw GraalError.shouldNotReachHere(); 455 } 456 } 457 } 458 setcc(AMD64MacroAssembler masm, Value result, ConditionFlag cond)459 private static void setcc(AMD64MacroAssembler masm, Value result, ConditionFlag cond) { 460 switch ((AMD64Kind) result.getPlatformKind()) { 461 case BYTE: 462 case WORD: 463 case DWORD: 464 masm.setl(cond, asRegister(result)); 465 break; 466 case QWORD: 467 masm.setq(cond, asRegister(result)); 468 break; 469 default: 470 throw GraalError.shouldNotReachHere(); 471 } 472 } 473 intCond(Condition cond)474 private static ConditionFlag intCond(Condition cond) { 475 switch (cond) { 476 case EQ: 477 return ConditionFlag.Equal; 478 case NE: 479 return ConditionFlag.NotEqual; 480 case LT: 481 return ConditionFlag.Less; 482 case LE: 483 return ConditionFlag.LessEqual; 484 case GE: 485 return ConditionFlag.GreaterEqual; 486 case GT: 487 return ConditionFlag.Greater; 488 case BE: 489 return ConditionFlag.BelowEqual; 490 case AE: 491 return ConditionFlag.AboveEqual; 492 case AT: 493 return ConditionFlag.Above; 494 case BT: 495 return ConditionFlag.Below; 496 default: 497 throw GraalError.shouldNotReachHere(); 498 } 499 } 500 floatCond(Condition cond)501 private static ConditionFlag floatCond(Condition cond) { 502 switch (cond) { 503 case EQ: 504 return ConditionFlag.Equal; 505 case NE: 506 return ConditionFlag.NotEqual; 507 case LT: 508 return ConditionFlag.Below; 509 case LE: 510 return ConditionFlag.BelowEqual; 511 case GE: 512 return ConditionFlag.AboveEqual; 513 case GT: 514 return ConditionFlag.Above; 515 default: 516 throw GraalError.shouldNotReachHere(); 517 } 518 } 519 trueOnUnordered(Condition condition)520 public static boolean trueOnUnordered(Condition condition) { 521 return trueOnUnordered(floatCond(condition)); 522 } 523 trueOnUnordered(ConditionFlag condition)524 private static boolean trueOnUnordered(ConditionFlag condition) { 525 switch (condition) { 526 case AboveEqual: 527 case NotEqual: 528 case Above: 529 case Less: 530 case Overflow: 531 return false; 532 case Equal: 533 case BelowEqual: 534 case Below: 535 case GreaterEqual: 536 case NoOverflow: 537 return true; 538 default: 539 throw GraalError.shouldNotReachHere(); 540 } 541 } 542 } 543