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 &lt; y then goto A
836       * </code>
837       * becomes:
838       * <code>
839       * if y &gte; 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    }