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 &lt; y then goto A
826       * </code>
827       * becomes:
828       * <code>
829       * if y &gte; 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    }