001 /* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013 package org.jikesrvm.compilers.opt.ir.operand; 014 015 import org.jikesrvm.compilers.opt.OptimizingCompilerException; 016 import org.vmmagic.unboxed.Address; 017 import org.jikesrvm.runtime.Magic; 018 019 /** 020 * Encodes the condition codes for branches. 021 * 022 * @see Operand 023 */ 024 public final class ConditionOperand extends Operand { 025 026 /* signed integer arithmetic */ 027 public static final int EQUAL = 0; 028 public static final int NOT_EQUAL = 1; 029 public static final int LESS = 2; 030 public static final int GREATER_EQUAL = 3; 031 public static final int GREATER = 4; 032 public static final int LESS_EQUAL = 5; 033 034 /* unsigned integer arithmetic */ 035 public static final int HIGHER = 6; 036 public static final int LOWER = 7; 037 public static final int HIGHER_EQUAL = 8; 038 public static final int LOWER_EQUAL = 9; 039 040 /* floating-point arithmethic */ 041 // branches that fall through when unordered 042 /** Branch if == (equivalent to CMPG_EQUAL) */ 043 public static final int CMPL_EQUAL = 10; 044 /** Branch if > */ 045 public static final int CMPL_GREATER = 11; 046 /** Branch if < */ 047 public static final int CMPG_LESS = 12; 048 /** Branch if >= */ 049 public static final int CMPL_GREATER_EQUAL = 13; 050 /** Branch if <= */ 051 public static final int CMPG_LESS_EQUAL = 14; 052 // branches that are taken when unordered 053 /** Branch if != (equivalent to CMPG_NOT_EQUAL) */ 054 public static final int CMPL_NOT_EQUAL = 17; 055 /** Branch if < or unordered */ 056 public static final int CMPL_LESS = 18; 057 /** Branch if >= or unordered */ 058 public static final int CMPG_GREATER_EQUAL = 19; 059 /** Branch if > or unordered */ 060 public static final int CMPG_GREATER = 20; 061 /** Branch if <= or unordered */ 062 public static final int CMPL_LESS_EQUAL = 21; 063 064 /** 065 * Value of this operand. 066 */ 067 public int value; 068 069 /** 070 * @param code the condition code 071 */ 072 private ConditionOperand(int code) { 073 value = code; 074 } 075 076 /** 077 * Create the condition code operand for EQUAL 078 * 079 * @return a new condition code operand 080 */ 081 public static ConditionOperand EQUAL() { 082 return new ConditionOperand(EQUAL); 083 } 084 085 /** 086 * Create the condition code operand for NOT_EQUAL 087 * 088 * @return a newly created condition code operand 089 */ 090 public static ConditionOperand NOT_EQUAL() { 091 return new ConditionOperand(NOT_EQUAL); 092 } 093 094 /** 095 * Create the condition code operand for LESS 096 * 097 * @return a newly created condition code operand 098 */ 099 public static ConditionOperand LESS() { 100 return new ConditionOperand(LESS); 101 } 102 103 /** 104 * Create the condition code operand for GREATER_EQUAL 105 * 106 * @return a newly created condition code operand 107 */ 108 public static ConditionOperand GREATER_EQUAL() { 109 return new ConditionOperand(GREATER_EQUAL); 110 } 111 112 /** 113 * Create the condition code operand for GREATER 114 * 115 * @return a newly created condition code operand 116 */ 117 public static ConditionOperand GREATER() { 118 return new ConditionOperand(GREATER); 119 } 120 121 /** 122 * Create the condition code operand for LESS_EQUAL 123 * 124 * @return a newly created condition code operand 125 */ 126 public static ConditionOperand LESS_EQUAL() { 127 return new ConditionOperand(LESS_EQUAL); 128 } 129 130 /** 131 * Create the condition code operand for HIGHER 132 * 133 * @return a newly created condition code operand 134 */ 135 public static ConditionOperand HIGHER() { 136 return new ConditionOperand(HIGHER); 137 } 138 139 /** 140 * Create the condition code operand for LOWER 141 * 142 * @return a newly created condition code operand 143 */ 144 public static ConditionOperand LOWER() { 145 return new ConditionOperand(LOWER); 146 } 147 148 /** 149 * Create the condition code operand for HIGHER_EQUAL 150 * 151 * @return a newly created condition code operand 152 */ 153 public static ConditionOperand HIGHER_EQUAL() { 154 return new ConditionOperand(HIGHER_EQUAL); 155 } 156 157 /** 158 * Create the condition code operand for LOWER_EQUAL 159 * 160 * @return a newly created condition code operand 161 */ 162 public static ConditionOperand LOWER_EQUAL() { 163 return new ConditionOperand(LOWER_EQUAL); 164 } 165 166 /** 167 * Is the condition code EQUAL? 168 * 169 * @return <code>true</code> if it is or <code>false</code> if it is not 170 */ 171 public boolean isEQUAL() { 172 return value == EQUAL; 173 } 174 175 /** 176 * Is the condition code NOT_EQUAL? 177 * 178 * @return <code>true</code> if it is or <code>false</code> if it is not 179 */ 180 public boolean isNOT_EQUAL() { 181 return value == NOT_EQUAL; 182 } 183 184 /** 185 * Is the condition code LESS EQUAL? 186 * 187 * @return <code>true</code> if it is or <code>false</code> if it is not 188 */ 189 public boolean isLESS_EQUAL() { 190 return value == LESS_EQUAL; 191 } 192 193 /** 194 * Is the condition code GREATER_EQUAL? 195 * 196 * @return <code>true</code> if it is or <code>false</code> if it is not 197 */ 198 public boolean isGREATER_EQUAL() { 199 return value == GREATER_EQUAL; 200 } 201 202 /** 203 * Is the condition code GREATER? 204 * 205 * @return <code>true</code> if it is or <code>false</code> if it is not 206 */ 207 public boolean isGREATER() { 208 return value == GREATER; 209 } 210 211 /** 212 * Is the condition code LESS? 213 * 214 * @return <code>true</code> if it is or <code>false</code> if it is not 215 */ 216 public boolean isLESS() { 217 return value == LESS; 218 } 219 220 /** 221 * Is the condition code HIGHER? 222 * 223 * @return <code>true</code> if it is or <code>false</code> if it is not 224 */ 225 public boolean isHIGHER() { 226 return value == HIGHER; 227 } 228 229 /** 230 * Is the condition code LOWER? 231 * 232 * @return <code>true</code> if it is or <code>false</code> if it is not 233 */ 234 public boolean isLOWER() { 235 return value == LOWER; 236 } 237 238 /** 239 * Is the condition code HIGHER_EQUAL? 240 * 241 * @return <code>true</code> if it is or <code>false</code> if it is not 242 */ 243 public boolean isHIGHER_EQUAL() { 244 return value == HIGHER_EQUAL; 245 } 246 247 /** 248 * Is the condition code LOWER_EQUAL? 249 * 250 * @return <code>true</code> if it is or <code>false</code> if it is not 251 */ 252 public boolean isLOWER_EQUAL() { 253 return value == LOWER_EQUAL; 254 } 255 256 /** 257 * Is the condition code an unsigned comparison? 258 * @return <code>true</code> if it is or <code>false</code> if it is not 259 */ 260 public boolean isUNSIGNED() { 261 switch (value) { 262 case HIGHER: 263 case LOWER: 264 case HIGHER_EQUAL: 265 case LOWER_EQUAL: 266 return true; 267 default: 268 return false; 269 } 270 } 271 272 /** 273 * Is the condition code a floating point compare? 274 * @return <code>true</code> if it is or <code>false</code> if it is not 275 */ 276 public boolean isFLOATINGPOINT() { 277 switch (value) { 278 case CMPL_EQUAL: 279 case CMPL_GREATER: 280 case CMPG_LESS: 281 case CMPL_GREATER_EQUAL: 282 case CMPG_LESS_EQUAL: 283 case CMPL_NOT_EQUAL: 284 case CMPL_LESS: 285 case CMPG_GREATER_EQUAL: 286 case CMPG_GREATER: 287 case CMPL_LESS_EQUAL: 288 return true; 289 default: 290 return false; 291 } 292 } 293 294 /** 295 * Will this floating point compare branch if the results are 296 * unordered? 297 * @return <code>true</code> if it is or <code>false</code> if it is not 298 */ 299 public boolean branchIfUnordered() { 300 switch (value) { 301 case CMPL_EQUAL: 302 case CMPL_GREATER: 303 case CMPG_LESS: 304 case CMPL_GREATER_EQUAL: 305 case CMPG_LESS_EQUAL: 306 return false; 307 case CMPL_NOT_EQUAL: 308 case CMPL_LESS: 309 case CMPG_GREATER_EQUAL: 310 case CMPG_GREATER: 311 case CMPL_LESS_EQUAL: 312 return true; 313 default: 314 throw new OptimizingCompilerException("invalid condition " + this); 315 } 316 } 317 318 /** 319 * Convert this integer compare to a floating point cmpl 320 * compare. Used during BC2IR. 321 */ 322 public void translateCMPL() { 323 switch (value) { 324 case EQUAL: 325 value = CMPL_EQUAL; 326 break; 327 case NOT_EQUAL: 328 value = CMPL_NOT_EQUAL; 329 break; 330 case LESS: 331 value = CMPL_LESS; 332 break; 333 case GREATER_EQUAL: 334 value = CMPL_GREATER_EQUAL; 335 break; 336 case GREATER: 337 value = CMPL_GREATER; 338 break; 339 case LESS_EQUAL: 340 value = CMPL_LESS_EQUAL; 341 break; 342 default: 343 throw new OptimizingCompilerException("invalid condition " + this); 344 } 345 } 346 347 /** 348 * Convert this integer compare to a floating point cmpg 349 * compare. Used during BC2IR. 350 */ 351 public void translateCMPG() { 352 switch (value) { 353 case EQUAL: 354 value = CMPL_EQUAL; 355 break; 356 case NOT_EQUAL: 357 value = CMPL_NOT_EQUAL; 358 break; 359 case LESS: 360 value = CMPG_LESS; 361 break; 362 case GREATER_EQUAL: 363 value = CMPG_GREATER_EQUAL; 364 break; 365 case GREATER: 366 value = CMPG_GREATER; 367 break; 368 case LESS_EQUAL: 369 value = CMPG_LESS_EQUAL; 370 break; 371 default: 372 throw new OptimizingCompilerException("invalid condition " + this); 373 } 374 } 375 376 /** 377 * Convert this floating point compare to the equivalent unsigned 378 * integer compare. Used during IA-32 BURS.<p> 379 * 380 * NB this doesn't respect ordered/unordered operation, so it 381 * should only be used when it's safe to. 382 */ 383 public ConditionOperand translateUNSIGNED() { 384 switch (value) { 385 case CMPL_EQUAL: 386 value = EQUAL; 387 break; 388 case CMPL_GREATER: 389 value = HIGHER; 390 break; 391 case CMPG_LESS: 392 value = LOWER; 393 break; 394 case CMPL_GREATER_EQUAL: 395 value = HIGHER_EQUAL; 396 break; 397 case CMPG_LESS_EQUAL: 398 value = LOWER_EQUAL; 399 break; 400 case CMPL_NOT_EQUAL: 401 value = NOT_EQUAL; 402 break; 403 case CMPL_LESS: 404 value = LOWER; 405 break; 406 case CMPG_GREATER_EQUAL: 407 value = HIGHER_EQUAL; 408 break; 409 case CMPG_GREATER: 410 value = HIGHER; 411 break; 412 case CMPL_LESS_EQUAL: 413 value = LOWER_EQUAL; 414 break; 415 default: 416 throw new OptimizingCompilerException("invalid condition " + this); 417 } 418 return this; 419 } 420 421 @Override 422 public Operand copy() { 423 return new ConditionOperand(value); 424 } 425 426 @Override 427 public boolean similar(Operand op) { 428 return (op instanceof ConditionOperand) && (((ConditionOperand) op).value == value); 429 } 430 431 public static final int FALSE = 0; 432 public static final int TRUE = 1; 433 public static final int UNKNOWN = 2; 434 435 /** 436 * Given two operands, evaluate the condition on them. 437 * 438 * @param v1 first operand to condition 439 * @param v2 second operand to condition 440 * @return <code>TRUE</code> if (v1 cond v2) or 441 * <code>FALSE</code> if !(v1 cond v2) or 442 * <code>UNKNOWN</code> 443 */ 444 public int evaluate(Operand v1, Operand v2) { 445 if (v1.isAddressConstant()) { 446 if (v2.isAddressConstant()) { 447 return evaluate(v1.asAddressConstant().value, v2.asAddressConstant().value); 448 } else if (v2.isNullConstant()) { 449 return evaluate(v1.asAddressConstant().value, Address.zero()); 450 } else if (v2.isIntConstant()) { 451 return evaluate(v1.asAddressConstant().value, Address.fromIntSignExtend(v2.asIntConstant().value)); 452 } else if (v2.isObjectConstant() && !v2.isMovableObjectConstant()) { 453 return evaluate(v1.asAddressConstant().value, 454 Magic.objectAsAddress(v2.asObjectConstant().value)); 455 } 456 } else if (v1.isIntConstant()) { 457 if (v2.isIntConstant()) { 458 return evaluate(v1.asIntConstant().value, v2.asIntConstant().value); 459 } else if (v2.isNullConstant()) { 460 return evaluate(v1.asIntConstant().value, 0); 461 } else if (v2.isAddressConstant()) { 462 return evaluate(Address.fromIntSignExtend(v1.asIntConstant().value), v2.asAddressConstant().value); 463 } else if (v2.isObjectConstant() && !v2.isMovableObjectConstant()) { 464 return evaluate(Address.fromIntSignExtend(v1.asIntConstant().value), 465 Magic.objectAsAddress(v2.asObjectConstant().value)); 466 } 467 } else if (v1.isLongConstant()) { 468 if (v2.isLongConstant()) { 469 return evaluate(v1.asLongConstant().value, v2.asLongConstant().value); 470 } 471 } else if (v1.isFloatConstant()) { 472 if (v2.isFloatConstant()) { 473 return evaluate(v1.asFloatConstant().value, v2.asFloatConstant().value); 474 } 475 } else if (v1.isDoubleConstant()) { 476 if (v2.isDoubleConstant()) { 477 return evaluate(v1.asDoubleConstant().value, v2.asDoubleConstant().value); 478 } 479 } else if (v1.isObjectConstant()) { 480 if (v2.isObjectConstant()) { 481 if (!v1.isMovableObjectConstant() && !v2.isMovableObjectConstant()) { 482 return evaluate(Magic.objectAsAddress(v1.asObjectConstant().value), 483 Magic.objectAsAddress(v2.asObjectConstant().value)); 484 } else if (isEQUAL()) { 485 return (v1.asObjectConstant().value == v2.asObjectConstant().value) ? TRUE : FALSE; 486 } else if (isNOT_EQUAL()) { 487 return (v1.asObjectConstant().value != v2.asObjectConstant().value) ? TRUE : FALSE; 488 } 489 } 490 if (v2.isNullConstant() || (v2.isIntConstant() && v2.asIntConstant().value == 0)) { 491 return evaluate(1,0); 492 } 493 if (!v1.isMovableObjectConstant()) { 494 if (v2.isIntConstant()) { 495 return evaluate(Magic.objectAsAddress(v1.asObjectConstant().value), 496 Address.fromIntSignExtend(v2.asIntConstant().value)); 497 } else if (v2.isAddressConstant()) { 498 return evaluate(Magic.objectAsAddress(v1.asObjectConstant().value), 499 v2.asAddressConstant().value); 500 } else if (v2.isNullConstant()) { 501 return evaluate(Magic.objectAsAddress(v1.asObjectConstant().value), 502 Address.zero()); 503 } 504 } 505 } else if (v1.isNullConstant()) { 506 if (v2.isNullConstant()) { 507 return evaluate(0, 0); 508 } else if (v2.isIntConstant()) { 509 return evaluate(0, v2.asIntConstant().value); 510 } else if (v2.isAddressConstant()) { 511 return evaluate(Address.zero(), v2.asAddressConstant().value); 512 } else if (v2.isObjectConstant()) { 513 if (!v2.isMovableObjectConstant()) { 514 return evaluate(Address.zero(), 515 Magic.objectAsAddress(v2.asObjectConstant().value)); 516 } else if (isEQUAL()) { 517 return FALSE; 518 } else if (isNOT_EQUAL()) { 519 return TRUE; 520 } 521 } 522 } else if (v1.similar(v2) && !isFLOATINGPOINT()) { 523 // comparisons of identical operands can be evaluated, except 524 // for floating point NaN cases 525 switch (value) { 526 case EQUAL: 527 case GREATER_EQUAL: 528 case LESS_EQUAL: 529 case HIGHER_EQUAL: 530 case LOWER_EQUAL: 531 return TRUE; 532 case NOT_EQUAL: 533 case LESS: 534 case GREATER: 535 case HIGHER: 536 case LOWER: 537 return FALSE; 538 default: 539 throw new OptimizingCompilerException("invalid condition " + this); 540 } 541 } 542 return UNKNOWN; 543 } 544 545 /** 546 * Given two ints, evaluate the condition on them. 547 * 548 * @param v1 first operand to condition 549 * @param v2 second operand to condition 550 * @return <code>TRUE</code> if (v1 cond v2) or 551 * <code>FALSE</code> if !(v1 cond v2) or 552 * <code>UNKNOWN</code> 553 */ 554 public int evaluate(int v1, int v2) { 555 switch (value) { 556 case EQUAL: 557 return (v1 == v2) ? TRUE : FALSE; 558 case NOT_EQUAL: 559 return (v1 != v2) ? TRUE : FALSE; 560 case GREATER: 561 return (v1 > v2) ? TRUE : FALSE; 562 case LESS: 563 return (v1 < v2) ? TRUE : FALSE; 564 case GREATER_EQUAL: 565 return (v1 >= v2) ? TRUE : FALSE; 566 case LESS_EQUAL: 567 return (v1 <= v2) ? TRUE : FALSE; 568 case LOWER: 569 if ((v1 >= 0 && v2 >= 0) || (v1 < 0 && v2 < 0)) { 570 return (v1 < v2) ? TRUE : FALSE; 571 } else if (v1 < 0) { 572 return FALSE; 573 } else { 574 return TRUE; 575 } 576 case LOWER_EQUAL: 577 if ((v1 >= 0 && v2 >= 0) || (v1 < 0 && v2 < 0)) { 578 return (v1 <= v2) ? TRUE : FALSE; 579 } else if (v1 < 0) { 580 return FALSE; 581 } else { 582 return TRUE; 583 } 584 case HIGHER: 585 if ((v1 >= 0 && v2 >= 0) || (v1 < 0 && v2 < 0)) { 586 return (v1 > v2) ? TRUE : FALSE; 587 } else if (v1 < 0) { 588 return TRUE; 589 } else { 590 return FALSE; 591 } 592 case HIGHER_EQUAL: 593 if ((v1 >= 0 && v2 >= 0) || (v1 < 0 && v2 < 0)) { 594 return (v1 >= v2) ? TRUE : FALSE; 595 } else if (v1 < 0) { 596 return TRUE; 597 } else { 598 return FALSE; 599 } 600 } 601 throw new OptimizingCompilerException("invalid condition " + this); 602 } 603 604 /** 605 * Given two longs, evaluate the condition on them. 606 * 607 * @param v1 first operand to condition 608 * @param v2 second operand to condition 609 * @return <code>TRUE</code> if (v1 cond v2) or 610 * <code>FALSE</code> if !(v1 cond v2) or 611 * <code>UNKNOWN</code> 612 */ 613 public int evaluate(long v1, long v2) { 614 switch (value) { 615 case EQUAL: 616 return (v1 == v2) ? TRUE : FALSE; 617 case NOT_EQUAL: 618 return (v1 != v2) ? TRUE : FALSE; 619 case GREATER: 620 return (v1 > v2) ? TRUE : FALSE; 621 case LESS: 622 return (v1 < v2) ? TRUE : FALSE; 623 case GREATER_EQUAL: 624 return (v1 >= v2) ? TRUE : FALSE; 625 case LESS_EQUAL: 626 return (v1 <= v2) ? TRUE : FALSE; 627 } 628 throw new OptimizingCompilerException("invalid condition " + this); 629 } 630 631 /** 632 * Given two floats, evaluate the condition on them. 633 * 634 * @param v1 first operand to condition 635 * @param v2 second operand to condition 636 * @return <code>true</code> if (v1 cond v2) or 637 * <code>false</code> otherwise 638 */ 639 public int evaluate(float v1, float v2) { 640 switch (value) { 641 // Return FALSE when UNORDERED 642 case CMPL_EQUAL: 643 return (v1 == v2) ? TRUE : FALSE; 644 case CMPL_GREATER: 645 return (v1 > v2) ? TRUE : FALSE; 646 case CMPG_LESS: 647 return (v1 < v2) ? TRUE : FALSE; 648 case CMPL_GREATER_EQUAL: 649 return (v1 >= v2) ? TRUE : FALSE; 650 case CMPG_LESS_EQUAL: 651 return (v1 <= v2) ? TRUE : FALSE; 652 // Return TRUE when UNORDERED 653 case CMPL_NOT_EQUAL: 654 return (v1 == v2) ? FALSE : TRUE; 655 case CMPL_LESS: 656 return (v1 >= v2) ? FALSE : TRUE; 657 case CMPG_GREATER_EQUAL: 658 return (v1 < v2) ? FALSE : TRUE; 659 case CMPG_GREATER: 660 return (v1 <= v2) ? FALSE : TRUE; 661 case CMPL_LESS_EQUAL: 662 return (v1 > v2) ? FALSE : TRUE; 663 } 664 throw new OptimizingCompilerException("invalid condition " + this); 665 } 666 667 /** 668 * Given two doubles, evaluate the condition on them. 669 * 670 * @param v1 first operand to condition 671 * @param v2 second operand to condition 672 * @return <code>true</code> if (v1 cond v2) or 673 * <code>false</code> otherwise 674 */ 675 public int evaluate(double v1, double v2) { 676 switch (value) { 677 // Return FALSE when UNORDERED 678 case CMPL_EQUAL: 679 return (v1 == v2) ? TRUE : FALSE; 680 case CMPL_GREATER: 681 return (v1 > v2) ? TRUE : FALSE; 682 case CMPG_LESS: 683 return (v1 < v2) ? TRUE : FALSE; 684 case CMPL_GREATER_EQUAL: 685 return (v1 >= v2) ? TRUE : FALSE; 686 case CMPG_LESS_EQUAL: 687 return (v1 <= v2) ? TRUE : FALSE; 688 // Return TRUE when UNORDERED 689 case CMPL_NOT_EQUAL: 690 return (v1 == v2) ? FALSE : TRUE; 691 case CMPL_LESS: 692 return (v1 >= v2) ? FALSE : TRUE; 693 case CMPG_GREATER_EQUAL: 694 return (v1 < v2) ? FALSE : TRUE; 695 case CMPG_GREATER: 696 return (v1 <= v2) ? FALSE : TRUE; 697 case CMPL_LESS_EQUAL: 698 return (v1 > v2) ? FALSE : TRUE; 699 } 700 throw new OptimizingCompilerException("invalid condition " + this); 701 } 702 703 /** 704 * Given two Addresses, evaluate the condition on them. 705 * 706 * @param v1 first operand to condition 707 * @param v2 second operand to condition 708 * @return <code>TRUE</code> if (v1 cond v2) or 709 * <code>FALSE</code> if !(v1 cond v2) or 710 * <code>UNKNOWN</code> 711 */ 712 public int evaluate(Address v1, Address v2) { 713 switch (value) { 714 case EQUAL: 715 return (v1.EQ(v2)) ? TRUE : FALSE; 716 case NOT_EQUAL: 717 return (v1.NE(v2)) ? TRUE : FALSE; 718 case GREATER: 719 return (v1.toWord().toOffset().sGT(v2.toWord().toOffset())) ? TRUE : FALSE; 720 case LESS: 721 return (v1.toWord().toOffset().sLT(v2.toWord().toOffset())) ? TRUE : FALSE; 722 case GREATER_EQUAL: 723 return (v1.toWord().toOffset().sGE(v2.toWord().toOffset())) ? TRUE : FALSE; 724 case LESS_EQUAL: 725 return (v1.toWord().toOffset().sLE(v2.toWord().toOffset())) ? TRUE : FALSE; 726 case LOWER: 727 return (v1.LT(v2)) ? TRUE : FALSE; 728 case LOWER_EQUAL: 729 return (v1.LE(v2)) ? TRUE : FALSE; 730 case HIGHER: 731 return (v1.GT(v2)) ? TRUE : FALSE; 732 case HIGHER_EQUAL: 733 return (v1.GE(v2)) ? TRUE : FALSE; 734 } 735 throw new OptimizingCompilerException("invalid condition " + this); 736 } 737 738 /** 739 * Flip the direction of the condition. Typical use is if you want to 740 * change the direction of a branch. i.e. to transform: 741 * <code> 742 * if (condition) goto A 743 * goto B 744 * A: 745 * </code> 746 * into: 747 * <code> 748 * if (!condition) goto B 749 * A: 750 * </code> 751 * Note that this is not the same as calling {@link #flipOperands}. 752 */ 753 public ConditionOperand flipCode() { 754 switch (value) { 755 case EQUAL: 756 value = NOT_EQUAL; 757 break; 758 case NOT_EQUAL: 759 value = EQUAL; 760 break; 761 case LESS: 762 value = GREATER_EQUAL; 763 break; 764 case LESS_EQUAL: 765 value = GREATER; 766 break; 767 case GREATER: 768 value = LESS_EQUAL; 769 break; 770 case GREATER_EQUAL: 771 value = LESS; 772 break; 773 case HIGHER: 774 value = LOWER_EQUAL; 775 break; 776 case LOWER: 777 value = HIGHER_EQUAL; 778 break; 779 case HIGHER_EQUAL: 780 value = LOWER; 781 break; 782 case LOWER_EQUAL: 783 value = HIGHER; 784 break; 785 case CMPL_EQUAL: 786 value = CMPL_NOT_EQUAL; 787 break; 788 case CMPL_GREATER: 789 value = CMPL_LESS_EQUAL; 790 break; 791 case CMPG_LESS: 792 value = CMPG_GREATER_EQUAL; 793 break; 794 case CMPL_GREATER_EQUAL: 795 value = CMPL_LESS; 796 break; 797 case CMPG_LESS_EQUAL: 798 value = CMPG_GREATER; 799 break; 800 case CMPL_NOT_EQUAL: 801 value = CMPL_EQUAL; 802 break; 803 case CMPL_LESS: 804 value = CMPL_GREATER_EQUAL; 805 break; 806 case CMPG_GREATER_EQUAL: 807 value = CMPG_LESS; 808 break; 809 case CMPG_GREATER: 810 value = CMPG_LESS_EQUAL; 811 break; 812 case CMPL_LESS_EQUAL: 813 value = CMPL_GREATER; 814 break; 815 default: 816 OptimizingCompilerException.UNREACHABLE(); 817 } 818 return this; 819 } 820 821 /** 822 * Change the condition code to allow the order of the operands to 823 * be flipped. i.e. So that: 824 * <code> 825 * if x < y then goto A 826 * </code> 827 * becomes: 828 * <code> 829 * if y >e; x then goto A 830 * </code> 831 * Note that this is not the same as calling {@link #flipCode}. 832 */ 833 public ConditionOperand flipOperands() { 834 switch (value) { 835 case EQUAL: 836 value = EQUAL; 837 break; 838 case NOT_EQUAL: 839 value = NOT_EQUAL; 840 break; 841 case LESS: 842 value = GREATER; 843 break; 844 case LESS_EQUAL: 845 value = GREATER_EQUAL; 846 break; 847 case GREATER: 848 value = LESS; 849 break; 850 case GREATER_EQUAL: 851 value = LESS_EQUAL; 852 break; 853 case HIGHER: 854 value = LOWER; 855 break; 856 case LOWER: 857 value = HIGHER; 858 break; 859 case HIGHER_EQUAL: 860 value = LOWER_EQUAL; 861 break; 862 case LOWER_EQUAL: 863 value = HIGHER_EQUAL; 864 break; 865 case CMPL_EQUAL: 866 value = CMPL_EQUAL; 867 break; 868 case CMPL_GREATER: 869 value = CMPG_LESS; 870 break; 871 case CMPG_LESS: 872 value = CMPL_GREATER; 873 break; 874 case CMPL_GREATER_EQUAL: 875 value = CMPG_LESS_EQUAL; 876 break; 877 case CMPG_LESS_EQUAL: 878 value = CMPL_GREATER_EQUAL; 879 break; 880 case CMPL_NOT_EQUAL: 881 value = CMPL_NOT_EQUAL; 882 break; 883 case CMPL_LESS: 884 value = CMPG_GREATER; 885 break; 886 case CMPG_GREATER_EQUAL: 887 value = CMPL_LESS_EQUAL; 888 break; 889 case CMPG_GREATER: 890 value = CMPL_LESS; 891 break; 892 case CMPL_LESS_EQUAL: 893 value = CMPG_GREATER_EQUAL; 894 break; 895 default: 896 OptimizingCompilerException.UNREACHABLE(); 897 } 898 return this; 899 } 900 901 /** 902 * Returns the string representation of this operand. Postfix 903 * meanings: 904 * <ul><li>U - unsigned comparison</li> 905 * <li>F - floating point compare that doesn't branch when 906 * operands are unordered</li> 907 * <li>FU - floating point compare that does branch when 908 * operands are unordered</li> 909 * </ul> 910 * 911 * @return a string representation of this operand. 912 */ 913 @Override 914 public String toString() { 915 switch (value) { 916 case EQUAL: 917 return "=="; 918 case NOT_EQUAL: 919 return "!="; 920 case LESS: 921 return "<"; 922 case LESS_EQUAL: 923 return "<="; 924 case GREATER: 925 return ">"; 926 case GREATER_EQUAL: 927 return ">="; 928 case HIGHER: 929 return ">U"; 930 case LOWER: 931 return "<U"; 932 case HIGHER_EQUAL: 933 return ">=U"; 934 case LOWER_EQUAL: 935 return "<=U"; 936 case CMPL_EQUAL: 937 return "==F"; 938 case CMPL_GREATER: 939 return ">F"; 940 case CMPG_LESS: 941 return "<F"; 942 case CMPL_GREATER_EQUAL: 943 return ">=F"; 944 case CMPG_LESS_EQUAL: 945 return "<=F"; 946 case CMPL_NOT_EQUAL: 947 return "!=FU"; 948 case CMPL_LESS: 949 return "<FU"; 950 case CMPG_GREATER_EQUAL: 951 return ">=FU"; 952 case CMPG_GREATER: 953 return ">FU"; 954 case CMPL_LESS_EQUAL: 955 return "<=FU"; 956 default: 957 return "UNKNOWN"; 958 } 959 } 960 }