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 comparision?
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 - NB this doesn't respect
379 * ordered/unordered operation, so it should only be used when it's
380 * safe to.
381 */
382 public ConditionOperand translateUNSIGNED() {
383 switch (value) {
384 case CMPL_EQUAL:
385 value = EQUAL;
386 break;
387 case CMPL_GREATER:
388 value = HIGHER;
389 break;
390 case CMPG_LESS:
391 value = LOWER;
392 break;
393 case CMPL_GREATER_EQUAL:
394 value = HIGHER_EQUAL;
395 break;
396 case CMPG_LESS_EQUAL:
397 value = LOWER_EQUAL;
398 break;
399 case CMPL_NOT_EQUAL:
400 value = NOT_EQUAL;
401 break;
402 case CMPL_LESS:
403 value = LOWER;
404 break;
405 case CMPG_GREATER_EQUAL:
406 value = HIGHER_EQUAL;
407 break;
408 case CMPG_GREATER:
409 value = HIGHER;
410 break;
411 case CMPL_LESS_EQUAL:
412 value = LOWER_EQUAL;
413 break;
414 default:
415 throw new OptimizingCompilerException("invalid condition " + this);
416 }
417 return this;
418 }
419
420 /**
421 * Return a new operand that is semantically equivalent to <code>this</code>.
422 *
423 * @return a copy of <code>this</code>
424 */
425 public Operand copy() {
426 return new ConditionOperand(value);
427 }
428
429 /**
430 * Are two operands semantically equivalent?
431 *
432 * @param op other operand
433 * @return <code>true</code> if <code>this</code> and <code>op</code>
434 * are semantically equivalent or <code>false</code>
435 * if they are not.
436 */
437 public boolean similar(Operand op) {
438 return (op instanceof ConditionOperand) && (((ConditionOperand) op).value == value);
439 }
440
441 public static final int FALSE = 0;
442 public static final int TRUE = 1;
443 public static final int UNKNOWN = 2;
444
445 /**
446 * Given two operands, evaluate the condition on them.
447 *
448 * @param v1 first operand to condition
449 * @param v2 second operand to condition
450 * @return <code>TRUE</code> if (v1 cond v2) or
451 * <code>FALSE</code> if !(v1 cond v2) or
452 * <code>UNKNOWN</code>
453 */
454 public int evaluate(Operand v1, Operand v2) {
455 if (v1.isAddressConstant()) {
456 if (v2.isAddressConstant()) {
457 return evaluate(v1.asAddressConstant().value, v2.asAddressConstant().value);
458 } else if (v2.isNullConstant()) {
459 return evaluate(v1.asAddressConstant().value, Address.zero());
460 } else if (v2.isIntConstant()) {
461 return evaluate(v1.asAddressConstant().value, Address.fromIntSignExtend(v2.asIntConstant().value));
462 } else if (v2.isObjectConstant() && !v2.isMovableObjectConstant()) {
463 return evaluate(v1.asAddressConstant().value,
464 Magic.objectAsAddress(v2.asObjectConstant().value));
465 }
466 } else if (v1.isIntConstant()) {
467 if (v2.isIntConstant()) {
468 return evaluate(v1.asIntConstant().value, v2.asIntConstant().value);
469 } else if (v2.isNullConstant()) {
470 return evaluate(v1.asIntConstant().value, 0);
471 } else if (v2.isAddressConstant()) {
472 return evaluate(Address.fromIntSignExtend(v1.asIntConstant().value), v2.asAddressConstant().value);
473 } else if (v2.isObjectConstant() && !v2.isMovableObjectConstant()) {
474 return evaluate(Address.fromIntSignExtend(v1.asIntConstant().value),
475 Magic.objectAsAddress(v2.asObjectConstant().value));
476 }
477 } else if (v1.isLongConstant()) {
478 if (v2.isLongConstant()) {
479 return evaluate(v1.asLongConstant().value, v2.asLongConstant().value);
480 }
481 } else if (v1.isFloatConstant()) {
482 if (v2.isFloatConstant()) {
483 return evaluate(v1.asFloatConstant().value, v2.asFloatConstant().value);
484 }
485 } else if (v1.isDoubleConstant()) {
486 if (v2.isDoubleConstant()) {
487 return evaluate(v1.asDoubleConstant().value, v2.asDoubleConstant().value);
488 }
489 } else if (v1.isObjectConstant()) {
490 if (v2.isObjectConstant()) {
491 if (!v1.isMovableObjectConstant() && !v2.isMovableObjectConstant()) {
492 return evaluate(Magic.objectAsAddress(v1.asObjectConstant().value),
493 Magic.objectAsAddress(v2.asObjectConstant().value));
494 } else if (isEQUAL()) {
495 return (v1.asObjectConstant().value == v2.asObjectConstant().value) ? TRUE : FALSE;
496 } else if (isNOT_EQUAL()) {
497 return (v1.asObjectConstant().value != v2.asObjectConstant().value) ? TRUE : FALSE;
498 }
499 }
500 if (v2.isNullConstant() || (v2.isIntConstant() && v2.asIntConstant().value == 0)) {
501 return evaluate(1,0);
502 }
503 if (!v1.isMovableObjectConstant()) {
504 if (v2.isIntConstant()) {
505 return evaluate(Magic.objectAsAddress(v1.asObjectConstant().value),
506 Address.fromIntSignExtend(v2.asIntConstant().value));
507 } else if (v2.isAddressConstant()) {
508 return evaluate(Magic.objectAsAddress(v1.asObjectConstant().value),
509 v2.asAddressConstant().value);
510 } else if (v2.isNullConstant()) {
511 return evaluate(Magic.objectAsAddress(v1.asObjectConstant().value),
512 Address.zero());
513 }
514 }
515 } else if (v1.isNullConstant()) {
516 if (v2.isNullConstant()) {
517 return evaluate(0, 0);
518 } else if (v2.isIntConstant()) {
519 return evaluate(0, v2.asIntConstant().value);
520 } else if (v2.isAddressConstant()) {
521 return evaluate(Address.zero(), v2.asAddressConstant().value);
522 } else if (v2.isObjectConstant()) {
523 if (!v2.isMovableObjectConstant()) {
524 return evaluate(Address.zero(),
525 Magic.objectAsAddress(v2.asObjectConstant().value));
526 } else if (isEQUAL()) {
527 return FALSE;
528 } else if (isNOT_EQUAL()) {
529 return TRUE;
530 }
531 }
532 } else if (v1.similar(v2) && !isFLOATINGPOINT()) {
533 // comparisons of identical operands can be evaluated, except
534 // for floating point NaN cases
535 switch (value) {
536 case EQUAL:
537 case GREATER_EQUAL:
538 case LESS_EQUAL:
539 case HIGHER_EQUAL:
540 case LOWER_EQUAL:
541 return TRUE;
542 case NOT_EQUAL:
543 case LESS:
544 case GREATER:
545 case HIGHER:
546 case LOWER:
547 return FALSE;
548 default:
549 throw new OptimizingCompilerException("invalid condition " + this);
550 }
551 }
552 return UNKNOWN;
553 }
554
555 /**
556 * Given two ints, evaluate the condition on them.
557 *
558 * @param v1 first operand to condition
559 * @param v2 second operand to condition
560 * @return <code>TRUE</code> if (v1 cond v2) or
561 * <code>FALSE</code> if !(v1 cond v2) or
562 * <code>UNKNOWN</code>
563 */
564 public int evaluate(int v1, int v2) {
565 switch (value) {
566 case EQUAL:
567 return (v1 == v2) ? TRUE : FALSE;
568 case NOT_EQUAL:
569 return (v1 != v2) ? TRUE : FALSE;
570 case GREATER:
571 return (v1 > v2) ? TRUE : FALSE;
572 case LESS:
573 return (v1 < v2) ? TRUE : FALSE;
574 case GREATER_EQUAL:
575 return (v1 >= v2) ? TRUE : FALSE;
576 case LESS_EQUAL:
577 return (v1 <= v2) ? TRUE : FALSE;
578 case LOWER:
579 if ((v1 >= 0 && v2 >= 0) || (v1 < 0 && v2 < 0)) {
580 return (v1 < v2) ? TRUE : FALSE;
581 } else if (v1 < 0) {
582 return FALSE;
583 } else {
584 return TRUE;
585 }
586 case LOWER_EQUAL:
587 if ((v1 >= 0 && v2 >= 0) || (v1 < 0 && v2 < 0)) {
588 return (v1 <= v2) ? TRUE : FALSE;
589 } else if (v1 < 0) {
590 return FALSE;
591 } else {
592 return TRUE;
593 }
594 case HIGHER:
595 if ((v1 >= 0 && v2 >= 0) || (v1 < 0 && v2 < 0)) {
596 return (v1 > v2) ? TRUE : FALSE;
597 } else if (v1 < 0) {
598 return TRUE;
599 } else {
600 return FALSE;
601 }
602 case HIGHER_EQUAL:
603 if ((v1 >= 0 && v2 >= 0) || (v1 < 0 && v2 < 0)) {
604 return (v1 >= v2) ? TRUE : FALSE;
605 } else if (v1 < 0) {
606 return TRUE;
607 } else {
608 return FALSE;
609 }
610 }
611 throw new OptimizingCompilerException("invalid condition " + this);
612 }
613
614 /**
615 * Given two longs, evaluate the condition on them.
616 *
617 * @param v1 first operand to condition
618 * @param v2 second operand to condition
619 * @return <code>TRUE</code> if (v1 cond v2) or
620 * <code>FALSE</code> if !(v1 cond v2) or
621 * <code>UNKNOWN</code>
622 */
623 public int evaluate(long v1, long v2) {
624 switch (value) {
625 case EQUAL:
626 return (v1 == v2) ? TRUE : FALSE;
627 case NOT_EQUAL:
628 return (v1 != v2) ? TRUE : FALSE;
629 case GREATER:
630 return (v1 > v2) ? TRUE : FALSE;
631 case LESS:
632 return (v1 < v2) ? TRUE : FALSE;
633 case GREATER_EQUAL:
634 return (v1 >= v2) ? TRUE : FALSE;
635 case LESS_EQUAL:
636 return (v1 <= v2) ? TRUE : FALSE;
637 }
638 throw new OptimizingCompilerException("invalid condition " + this);
639 }
640
641 /**
642 * Given two floats, evaluate the condition on them.
643 *
644 * @param v1 first operand to condition
645 * @param v2 second operand to condition
646 * @return <code>true</code> if (v1 cond v2) or
647 * <code>false</code> otherwise
648 */
649 public int evaluate(float v1, float v2) {
650 switch (value) {
651 // Return FALSE when UNORDERED
652 case CMPL_EQUAL:
653 return (v1 == v2) ? TRUE : FALSE;
654 case CMPL_GREATER:
655 return (v1 > v2) ? TRUE : FALSE;
656 case CMPG_LESS:
657 return (v1 < v2) ? TRUE : FALSE;
658 case CMPL_GREATER_EQUAL:
659 return (v1 >= v2) ? TRUE : FALSE;
660 case CMPG_LESS_EQUAL:
661 return (v1 <= v2) ? TRUE : FALSE;
662 // Return TRUE when UNORDERED
663 case CMPL_NOT_EQUAL:
664 return (v1 == v2) ? FALSE : TRUE;
665 case CMPL_LESS:
666 return (v1 >= v2) ? FALSE : TRUE;
667 case CMPG_GREATER_EQUAL:
668 return (v1 < v2) ? FALSE : TRUE;
669 case CMPG_GREATER:
670 return (v1 <= v2) ? FALSE : TRUE;
671 case CMPL_LESS_EQUAL:
672 return (v1 > v2) ? FALSE : TRUE;
673 }
674 throw new OptimizingCompilerException("invalid condition " + this);
675 }
676
677 /**
678 * Given two doubles, evaluate the condition on them.
679 *
680 * @param v1 first operand to condition
681 * @param v2 second operand to condition
682 * @return <code>true</code> if (v1 cond v2) or
683 * <code>false</code> otherwise
684 */
685 public int evaluate(double v1, double v2) {
686 switch (value) {
687 // Return FALSE when UNORDERED
688 case CMPL_EQUAL:
689 return (v1 == v2) ? TRUE : FALSE;
690 case CMPL_GREATER:
691 return (v1 > v2) ? TRUE : FALSE;
692 case CMPG_LESS:
693 return (v1 < v2) ? TRUE : FALSE;
694 case CMPL_GREATER_EQUAL:
695 return (v1 >= v2) ? TRUE : FALSE;
696 case CMPG_LESS_EQUAL:
697 return (v1 <= v2) ? TRUE : FALSE;
698 // Return TRUE when UNORDERED
699 case CMPL_NOT_EQUAL:
700 return (v1 == v2) ? FALSE : TRUE;
701 case CMPL_LESS:
702 return (v1 >= v2) ? FALSE : TRUE;
703 case CMPG_GREATER_EQUAL:
704 return (v1 < v2) ? FALSE : TRUE;
705 case CMPG_GREATER:
706 return (v1 <= v2) ? FALSE : TRUE;
707 case CMPL_LESS_EQUAL:
708 return (v1 > v2) ? FALSE : TRUE;
709 }
710 throw new OptimizingCompilerException("invalid condition " + this);
711 }
712
713 /**
714 * Given two Addresses, evaluate the condition on them.
715 *
716 * @param v1 first operand to condition
717 * @param v2 second operand to condition
718 * @return <code>TRUE</code> if (v1 cond v2) or
719 * <code>FALSE</code> if !(v1 cond v2) or
720 * <code>UNKNOWN</code>
721 */
722 public int evaluate(Address v1, Address v2) {
723 switch (value) {
724 case EQUAL:
725 return (v1.EQ(v2)) ? TRUE : FALSE;
726 case NOT_EQUAL:
727 return (v1.NE(v2)) ? TRUE : FALSE;
728 case GREATER:
729 return (v1.toWord().toOffset().sGT(v2.toWord().toOffset())) ? TRUE : FALSE;
730 case LESS:
731 return (v1.toWord().toOffset().sLT(v2.toWord().toOffset())) ? TRUE : FALSE;
732 case GREATER_EQUAL:
733 return (v1.toWord().toOffset().sGE(v2.toWord().toOffset())) ? TRUE : FALSE;
734 case LESS_EQUAL:
735 return (v1.toWord().toOffset().sLE(v2.toWord().toOffset())) ? TRUE : FALSE;
736 case LOWER:
737 return (v1.LT(v2)) ? TRUE : FALSE;
738 case LOWER_EQUAL:
739 return (v1.LE(v2)) ? TRUE : FALSE;
740 case HIGHER:
741 return (v1.GT(v2)) ? TRUE : FALSE;
742 case HIGHER_EQUAL:
743 return (v1.GE(v2)) ? TRUE : FALSE;
744 }
745 throw new OptimizingCompilerException("invalid condition " + this);
746 }
747
748 /**
749 * Flip the direction of the condition. Typical use is if you want to
750 * change the direction of a branch. i.e. to transform:
751 * <code>
752 * if (condition) goto A
753 * goto B
754 * A:
755 * </code>
756 * into:
757 * <code>
758 * if (!condition) goto B
759 * A:
760 * </code>
761 * Note that this is not the same as calling {@link #flipOperands}.
762 */
763 public ConditionOperand flipCode() {
764 switch (value) {
765 case EQUAL:
766 value = NOT_EQUAL;
767 break;
768 case NOT_EQUAL:
769 value = EQUAL;
770 break;
771 case LESS:
772 value = GREATER_EQUAL;
773 break;
774 case LESS_EQUAL:
775 value = GREATER;
776 break;
777 case GREATER:
778 value = LESS_EQUAL;
779 break;
780 case GREATER_EQUAL:
781 value = LESS;
782 break;
783 case HIGHER:
784 value = LOWER_EQUAL;
785 break;
786 case LOWER:
787 value = HIGHER_EQUAL;
788 break;
789 case HIGHER_EQUAL:
790 value = LOWER;
791 break;
792 case LOWER_EQUAL:
793 value = HIGHER;
794 break;
795 case CMPL_EQUAL:
796 value = CMPL_NOT_EQUAL;
797 break;
798 case CMPL_GREATER:
799 value = CMPL_LESS_EQUAL;
800 break;
801 case CMPG_LESS:
802 value = CMPG_GREATER_EQUAL;
803 break;
804 case CMPL_GREATER_EQUAL:
805 value = CMPL_LESS;
806 break;
807 case CMPG_LESS_EQUAL:
808 value = CMPG_GREATER;
809 break;
810 case CMPL_NOT_EQUAL:
811 value = CMPL_EQUAL;
812 break;
813 case CMPL_LESS:
814 value = CMPL_GREATER_EQUAL;
815 break;
816 case CMPG_GREATER_EQUAL:
817 value = CMPG_LESS;
818 break;
819 case CMPG_GREATER:
820 value = CMPG_LESS_EQUAL;
821 break;
822 case CMPL_LESS_EQUAL:
823 value = CMPL_GREATER;
824 break;
825 default:
826 OptimizingCompilerException.UNREACHABLE();
827 }
828 return this;
829 }
830
831 /**
832 * Change the condition code to allow the order of the operands to
833 * be flipped. i.e. So that:
834 * <code>
835 * if x < y then goto A
836 * </code>
837 * becomes:
838 * <code>
839 * if y >e; x then goto A
840 * </code>
841 * Note that this is not the same as calling {@link #flipCode}.
842 */
843 public ConditionOperand flipOperands() {
844 switch (value) {
845 case EQUAL:
846 value = EQUAL;
847 break;
848 case NOT_EQUAL:
849 value = NOT_EQUAL;
850 break;
851 case LESS:
852 value = GREATER;
853 break;
854 case LESS_EQUAL:
855 value = GREATER_EQUAL;
856 break;
857 case GREATER:
858 value = LESS;
859 break;
860 case GREATER_EQUAL:
861 value = LESS_EQUAL;
862 break;
863 case HIGHER:
864 value = LOWER;
865 break;
866 case LOWER:
867 value = HIGHER;
868 break;
869 case HIGHER_EQUAL:
870 value = LOWER_EQUAL;
871 break;
872 case LOWER_EQUAL:
873 value = HIGHER_EQUAL;
874 break;
875 case CMPL_EQUAL:
876 value = CMPL_EQUAL;
877 break;
878 case CMPL_GREATER:
879 value = CMPG_LESS;
880 break;
881 case CMPG_LESS:
882 value = CMPL_GREATER;
883 break;
884 case CMPL_GREATER_EQUAL:
885 value = CMPG_LESS_EQUAL;
886 break;
887 case CMPG_LESS_EQUAL:
888 value = CMPL_GREATER_EQUAL;
889 break;
890 case CMPL_NOT_EQUAL:
891 value = CMPL_NOT_EQUAL;
892 break;
893 case CMPL_LESS:
894 value = CMPG_GREATER;
895 break;
896 case CMPG_GREATER_EQUAL:
897 value = CMPL_LESS_EQUAL;
898 break;
899 case CMPG_GREATER:
900 value = CMPL_LESS;
901 break;
902 case CMPL_LESS_EQUAL:
903 value = CMPG_GREATER_EQUAL;
904 break;
905 default:
906 OptimizingCompilerException.UNREACHABLE();
907 }
908 return this;
909 }
910
911 /**
912 * Returns the string representation of this operand. Postfix
913 * meanings:
914 * <ul><li>U - unsigned comparison</li>
915 * <li>F - floating point compare that doesn't branch when
916 * operands are unordered</li>
917 * <li>FU - floating point compare that does branch when
918 * operands are unordered</li>
919 * </ul>
920 *
921 * @return a string representation of this operand.
922 */
923 public String toString() {
924 switch (value) {
925 case EQUAL:
926 return "==";
927 case NOT_EQUAL:
928 return "!=";
929 case LESS:
930 return "<";
931 case LESS_EQUAL:
932 return "<=";
933 case GREATER:
934 return ">";
935 case GREATER_EQUAL:
936 return ">=";
937 case HIGHER:
938 return ">U";
939 case LOWER:
940 return "<U";
941 case HIGHER_EQUAL:
942 return ">=U";
943 case LOWER_EQUAL:
944 return "<=U";
945 case CMPL_EQUAL:
946 return "==F";
947 case CMPL_GREATER:
948 return ">F";
949 case CMPG_LESS:
950 return "<F";
951 case CMPL_GREATER_EQUAL:
952 return ">=F";
953 case CMPG_LESS_EQUAL:
954 return "<=F";
955 case CMPL_NOT_EQUAL:
956 return "!=FU";
957 case CMPL_LESS:
958 return "<FU";
959 case CMPG_GREATER_EQUAL:
960 return ">=FU";
961 case CMPG_GREATER:
962 return ">FU";
963 case CMPL_LESS_EQUAL:
964 return "<=FU";
965 default:
966 return "UNKNOWN";
967 }
968 }
969 }