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;
014    
015    import static org.jikesrvm.compilers.opt.ir.Operators.*;
016    
017    import java.util.Enumeration;
018    import java.util.HashSet;
019    import java.util.Iterator;
020    
021    import org.jikesrvm.VM;
022    import org.jikesrvm.classloader.TypeReference;
023    import org.jikesrvm.compilers.opt.ir.Binary;
024    import org.jikesrvm.compilers.opt.ir.BooleanCmp;
025    import org.jikesrvm.compilers.opt.ir.BoundsCheck;
026    import org.jikesrvm.compilers.opt.ir.CondMove;
027    import org.jikesrvm.compilers.opt.ir.GuardedBinary;
028    import org.jikesrvm.compilers.opt.ir.GuardedUnary;
029    import org.jikesrvm.compilers.opt.ir.IR;
030    import org.jikesrvm.compilers.opt.ir.IRTools;
031    import org.jikesrvm.compilers.opt.ir.IfCmp;
032    import org.jikesrvm.compilers.opt.ir.IfCmp2;
033    import org.jikesrvm.compilers.opt.ir.InstanceOf;
034    import org.jikesrvm.compilers.opt.ir.Instruction;
035    import org.jikesrvm.compilers.opt.ir.Move;
036    import org.jikesrvm.compilers.opt.ir.New;
037    import org.jikesrvm.compilers.opt.ir.NewArray;
038    import org.jikesrvm.compilers.opt.ir.NullCheck;
039    import org.jikesrvm.compilers.opt.ir.Register;
040    import org.jikesrvm.compilers.opt.ir.Unary;
041    import org.jikesrvm.compilers.opt.ir.ZeroCheck;
042    import org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand;
043    import org.jikesrvm.compilers.opt.ir.operand.BranchOperand;
044    import org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand;
045    import org.jikesrvm.compilers.opt.ir.operand.ConditionOperand;
046    import org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand;
047    import org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand;
048    import org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand;
049    import org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand;
050    import org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand;
051    import org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand;
052    import org.jikesrvm.compilers.opt.ir.operand.Operand;
053    import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand;
054    import org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand;
055    import org.jikesrvm.runtime.Magic;
056    import org.jikesrvm.runtime.RuntimeEntrypoints;
057    import org.vmmagic.unboxed.Address;
058    import org.vmmagic.unboxed.Word;
059    
060    /**
061     * This class simplifies expressions globally, if in SSA form, or locally within
062     * a basic block if not.
063     */
064    public class ExpressionFolding extends IRTools {
065      /**
066       * Only fold operations when the result of the 1st operation becomes dead
067       * after folding
068       * TODO: doesn't apply to local folding
069       */
070      private static final boolean RESTRICT_TO_DEAD_EXPRESSIONS = false;
071    
072      /**
073       * Fold across uninterruptible regions
074       */
075      private static final boolean FOLD_OVER_UNINTERRUPTIBLE = false;
076      /**
077       * Fold operations on ints
078       */
079      private static final boolean FOLD_INTS = true;
080      /**
081       * Fold operations on word like things
082       */
083      private static final boolean FOLD_REFS = true;
084      /**
085       * Fold operations on longs
086       */
087      private static final boolean FOLD_LONGS = true;
088      /**
089       * Fold operations on floats
090       */
091      private static final boolean FOLD_FLOATS = true;
092      /**
093       * Fold operations on doubles
094       */
095      private static final boolean FOLD_DOUBLES = true;
096    
097      /**
098       * Fold binary SUB operations
099       */
100      private static final boolean FOLD_SUBS = true;
101    
102      /**
103       * Fold binary ADD operations
104       */
105      private static final boolean FOLD_ADDS = true;
106    
107      /**
108       * Fold binary multiply operations
109       */
110      private static final boolean FOLD_MULTS = true;
111    
112      /**
113       * Fold binary divide operations
114       */
115      private static final boolean FOLD_DIVS = true;
116    
117      /**
118       * Fold binary shift left operations
119       */
120      private static final boolean FOLD_SHIFTLS = true;
121    
122      /**
123       * Fold binary shift right operations
124       */
125      private static final boolean FOLD_SHIFTRS = true;
126    
127      /**
128       * Fold binary CMP operations
129       */
130      private static final boolean FOLD_CMPS = true;
131    
132      /**
133       * Fold binary XOR operations
134       */
135      private static final boolean FOLD_XORS = true;
136    
137      /**
138       * Fold binary OR operations
139       */
140      private static final boolean FOLD_ORS = true;
141    
142      /**
143       * Fold binary AND operations
144       */
145      private static final boolean FOLD_ANDS = true;
146    
147      /**
148       * Fold unary NEG operations
149       */
150      private static final boolean FOLD_NEGS = true;
151    
152      /**
153       * Fold unary NOT operations
154       */
155      private static final boolean FOLD_NOTS = true;
156    
157      /**
158       * Fold operations that create a constant on the LHS? This may produce less
159       * optimal code on 2 address architectures where the constant would need
160       * loading into a register prior to the operation.
161       */
162      private static final boolean FOLD_CONSTANTS_TO_LHS = true;
163    
164      /**
165       * Fold IFCMP operations
166       */
167      private static final boolean FOLD_IFCMPS = true;
168    
169      /**
170       * Fold COND_MOVE operations
171       */
172      private static final boolean FOLD_CONDMOVES = true;
173    
174      /**
175       * Fold xxx_2xxx where the precision is increased then decreased achieving a
176       * nop effect
177       */
178      private static final boolean FOLD_2CONVERSION = true;
179    
180      /**
181       * Fold ZeroCheck where we're testing whether a value is 0 or not
182       */
183      private static final boolean FOLD_CHECKS = true;
184    
185      /**
186       * Print out debug information
187       */
188      private static final boolean VERBOSE = false;
189    
190      /**
191       * Perform expression folding on individual basic blocks
192       */
193      public static boolean performLocal(IR ir) {
194        Instruction outer = ir.cfg.entry().firstRealInstruction();
195        if (VERBOSE) {
196          System.out.println("Start of expression folding for: " + ir.method.toString());
197        }
198        boolean didSomething = false;
199        // Outer loop: walk over every instruction of basic block looking for candidates
200        while (outer != null) {
201          Register outerDef = isCandidateExpression(outer, false);
202          if (outerDef != null) {
203            if (VERBOSE) {
204              System.out.println("Found outer candidate of: " + outer.toString());
205            }
206            Instruction inner = outer.nextInstructionInCodeOrder();
207            // Inner loop: walk over instructions in block, after outer instruction,
208            // checking whether inner and outer could be folded together.
209            // if not check for a dependency that means there are potential hazards
210            // to stop the search
211            loop_over_inner_instructions:
212            while ((inner != null) && (inner.operator() != BBEND) && !inner.isGCPoint()) {
213              if (!FOLD_OVER_UNINTERRUPTIBLE &&
214                  ((inner.operator() == UNINT_BEGIN) || (inner.operator() == UNINT_END))) {
215                break loop_over_inner_instructions;
216              }
217              Register innerDef = isCandidateExpression(inner, false);
218              // 1. check for true dependence (does inner use outer's def?)
219              if (innerDef != null) {
220                if (VERBOSE) {
221                  System.out.println("Found inner candidate of: " + inner.toString());
222                }
223                RegisterOperand use = getUseFromCandidate(inner);
224                if ((use != null) && (use.getRegister() == outerDef)) {
225                  // Optimization case
226                  Instruction newInner;
227                  try {
228                    if (VERBOSE) {
229                      System.out.println("Trying to fold:" + outer.toString());
230                      System.out.println("          with:" + inner.toString());
231                    }
232                    newInner = transform(inner, outer);
233                  } catch (OptimizingCompilerException e) {
234                    OptimizingCompilerException newE = new OptimizingCompilerException("Error transforming " + outer + " ; " + inner);
235                    newE.initCause(e);
236                    throw newE;
237                  }
238                  if (newInner != null) {
239                    if (VERBOSE) {
240                      System.out.println("Replacing:" + inner.toString());
241                      System.out.println("     with:" + newInner.toString());
242                    }
243                    DefUse.replaceInstructionAndUpdateDU(inner, CPOS(inner,newInner));
244                    inner = newInner;
245                    didSomething = true;
246                  }
247                }
248              }
249              // 2. check for output dependence (does inner kill outer's def?)
250              if (innerDef == outerDef) {
251                if (VERBOSE) {
252                  System.out.println("Stopping search as innerDef == outerDef " + innerDef.toString());
253                }
254                break loop_over_inner_instructions;
255              }
256              if (innerDef == null) {
257                Enumeration<Operand> defs = inner.getDefs();
258                while(defs.hasMoreElements()) {
259                  Operand def = defs.nextElement();
260                  if (def.isRegister()) {
261                    Register defReg = def.asRegister().getRegister();
262                    if (defReg == outerDef) {
263                      if (VERBOSE) {
264                        System.out.println("Stopping search as innerDef == outerDef " + defReg.toString());
265                      }
266                      break loop_over_inner_instructions;
267                    }
268                  }
269                }
270              }
271              // 3. check for anti dependence (do we define something that outer uses?)
272              if (innerDef != null) {
273                Enumeration<Operand> uses = outer.getUses();
274                while(uses.hasMoreElements()) {
275                  Operand use = uses.nextElement();
276                  if (use.isRegister() && (use.asRegister().getRegister() == innerDef)) {
277                    if (VERBOSE) {
278                      System.out.println("Stopping search as anti-dependence " + use.toString());
279                    }
280                    break loop_over_inner_instructions;
281                  }
282                }
283              } else {
284                Enumeration<Operand> defs = inner.getDefs();
285                while(defs.hasMoreElements()) {
286                  Operand def = defs.nextElement();
287                  if (def.isRegister()) {
288                    Enumeration<Operand> uses = outer.getUses();
289                    while(uses.hasMoreElements()) {
290                      Operand use = uses.nextElement();
291                      if (use.similar(def)) {
292                        if (VERBOSE) {
293                          System.out.println("Stopping search as anti-dependence " + use.toString());
294                        }
295                        break loop_over_inner_instructions;
296                      }
297                    }
298                  }
299                }
300              }
301              inner = inner.nextInstructionInCodeOrder();
302            } // loop over inner instructions
303          }
304          outer = outer.nextInstructionInCodeOrder();
305        } // loop over outer instructions
306        return didSomething;
307      }
308    
309      /**
310       * Get the register that's used by the candidate instruction
311       * @param s the instruction
312       * @return register used by candidate or {@code null} if this isn't a candidate
313       */
314      private static RegisterOperand getUseFromCandidate(Instruction s) {
315        if (Binary.conforms(s)) {
316          return Binary.getVal1(s).asRegister();
317        } else if (GuardedBinary.conforms(s)) {
318          return GuardedBinary.getVal1(s).asRegister();
319        } else if (Unary.conforms(s)) {
320          return Unary.getVal(s).asRegister();
321        } else if (GuardedUnary.conforms(s)) {
322          return GuardedUnary.getVal(s).asRegister();
323        } else if (BooleanCmp.conforms(s)) {
324          return BooleanCmp.getVal1(s).asRegister();
325        } else if (IfCmp.conforms(s)) {
326          return IfCmp.getVal1(s).asRegister();
327        } else if (IfCmp2.conforms(s)) {
328          return IfCmp2.getVal1(s).asRegister();
329        } else if (CondMove.conforms(s)) {
330          return CondMove.getVal1(s).asRegister();
331        } else if (ZeroCheck.conforms(s)) {
332          return ZeroCheck.getValue(s).asRegister();
333        } else if (BoundsCheck.conforms(s)) {
334          return BoundsCheck.getRef(s).asRegister();
335        } else if (NullCheck.conforms(s)) {
336          return NullCheck.getRef(s).asRegister();
337        } else if (InstanceOf.conforms(s)) {
338          return InstanceOf.getRef(s).asRegister();
339        } else if (NewArray.conforms(s) || New.conforms(s)) {
340          return null;
341        } else {
342          OptimizingCompilerException.UNREACHABLE();
343          return null;
344        }
345      }
346    
347      /**
348       * Get the register that's defined by the candidate instruction
349       * @param first is this the first instruction?
350       * @param s the instruction
351       * @return register used by candidate or {@code null} if this isn't a candidate
352       */
353      private static RegisterOperand getDefFromCandidate(Instruction s, boolean first) {
354        if (Binary.conforms(s)) {
355          return Binary.getResult(s);
356        } else if (GuardedBinary.conforms(s)) {
357          return GuardedBinary.getResult(s);
358        } else if (Unary.conforms(s)) {
359          return Unary.getResult(s);
360        } else if (GuardedUnary.conforms(s)) {
361          return GuardedUnary.getResult(s);
362        } else if (BooleanCmp.conforms(s)) {
363          return BooleanCmp.getResult(s);
364        } else if (IfCmp.conforms(s)) {
365          if (first) {
366            return null;
367          } else {
368            return IfCmp.getGuardResult(s);
369          }
370        } else if (IfCmp2.conforms(s)) {
371          if (first) {
372            return null;
373          } else {
374            return IfCmp2.getGuardResult(s);
375          }
376        } else if (CondMove.conforms(s)) {
377          if (first) {
378            return null;
379          } else {
380            return CondMove.getResult(s);
381          }
382        } else if (ZeroCheck.conforms(s)) {
383          return ZeroCheck.getGuardResult(s);
384        } else if (BoundsCheck.conforms(s)) {
385          return BoundsCheck.getGuardResult(s);
386        } else if (NullCheck.conforms(s)) {
387          return NullCheck.getGuardResult(s);
388        } else if (InstanceOf.conforms(s)) {
389          return InstanceOf.getResult(s);
390        } else if (NewArray.conforms(s)) {
391          if (first) {
392            return NewArray.getResult(s).asRegister();
393          } else {
394            return null;
395          }
396        } else if (New.conforms(s)) {
397          if (first) {
398            return New.getResult(s).asRegister();
399          } else {
400            return null;
401          }
402        } else {
403          OptimizingCompilerException.UNREACHABLE();
404          return null;
405        }
406      }
407      /**
408       * Perform the transformation.
409       *
410       * If we have, in SSA form,
411       *
412       * <pre>
413       *    x = a op1 c1
414       *    y = x op2 c2
415       * </pre>
416       *
417       * where c1 and c2 are constants, replace the def of y by
418       *
419       * <pre>
420       * y = a op1 (c1 op3 c2)
421       * </pre>
422       *
423       * Where op1, op2 and op3 are add, subtract, multiply, and, or, xor and
424       * compare. Repeatedly apply transformation until all expressions are folded.
425       *
426       * <p>
427       * PRECONDITIONS: SSA form, register lists computed
428       *
429       * @param ir
430       *          the governing IR
431       */
432      public static void perform(IR ir) {
433        // Create a set of potential computations to fold.
434        HashSet<Register> candidates = new HashSet<Register>(20);
435    
436        for (Enumeration<Instruction> e = ir.forwardInstrEnumerator(); e.hasMoreElements();) {
437          Instruction s = e.nextElement();
438          // Check if s is a candidate for expression folding
439          Register r = isCandidateExpression(s, true);
440          if (r != null) {
441            candidates.add(r);
442          }
443        }
444    
445        if (RESTRICT_TO_DEAD_EXPRESSIONS) {
446          pruneCandidates(candidates);
447        }
448    
449        boolean didSomething = true;
450        while (didSomething) {
451          didSomething = false;
452    
453          iterate_over_candidates:
454          for (Iterator<Register> it = candidates.iterator(); it.hasNext();) {
455            Register r = it.next();
456            Instruction s = r.getFirstDef();
457            Operand val1 = getUseFromCandidate(s);
458            if (val1 == null) continue; // operator that's not being optimized
459            if (VERBOSE) {
460              System.out.println("Found candidate instruction: " + s.toString());
461            }
462            Instruction def = val1.asRegister().getRegister().getFirstDef();
463            // filter out moves to get the real defining instruction
464            while (Move.conforms(def)) {
465              Operand op = Move.getVal(def);
466              if (op.isRegister()) {
467                def = op.asRegister().getRegister().getFirstDef();
468              } else {
469                // The non-constant operand of the candidate expression is the
470                // result of moving a constant. Remove as a candidate and leave
471                // for constant propagation and simplification.
472                it.remove();
473                continue iterate_over_candidates;
474              }
475            }
476            if (candidates.contains(val1.asRegister().getRegister())) {
477              if (VERBOSE) {
478                System.out.println(" Found candidate definition: " + def.toString());
479              }
480              // check if the defining instruction has not mutated yet
481              if (isCandidateExpression(def, true) == null) {
482                if (VERBOSE) {
483                  System.out.println(" Ignoring definition that is no longer a candidate");
484                }
485                continue;
486              }
487    
488              Instruction newS = transform(s, def);
489              if (newS != null) {
490                if (VERBOSE) {
491                  System.out.println(" Replacing: " + s.toString() + "\n with:" + newS.toString());
492                }
493                // check if this expression is still an optimisation candidate
494                if (isCandidateExpression(newS, true) == null) {
495                  it.remove();
496                }
497                DefUse.replaceInstructionAndUpdateDU(s, CPOS(s,newS));
498                didSomething = true;
499              }
500            }
501          }
502        }
503      }
504    
505      /**
506       * Prune the candidate set; restrict candidates to only allow transformations
507       * that result in dead code to be eliminated
508       */
509      private static void pruneCandidates(HashSet<Register> candidates) {
510        for (Iterator<Register> i = candidates.iterator(); i.hasNext();) {
511          Register r = i.next();
512          Instruction s = r.getFirstDef();
513          Operand val1 = getUseFromCandidate(s);
514          if (val1 == null) continue; // operator that's not being optimized
515    
516          if (VM.VerifyAssertions) {
517            VM._assert(val1.isRegister(), "Error with val1 of " + s);
518          }
519    
520          Register v1 = val1.asRegister().getRegister();
521          if (candidates.contains(v1)) {
522            Enumeration<RegisterOperand> uses = DefUse.uses(v1);
523            while (uses.hasMoreElements()) {
524              RegisterOperand op = uses.nextElement();
525              Instruction u = op.instruction;
526              if ((isCandidateExpression(u, true) == null) && !Move.conforms(u)) {
527                i.remove();
528                break;
529              }
530            }
531          }
532        }
533      }
534    
535      /**
536       * Perform the transformation on the instruction
537       *
538       * @param s
539       *          the instruction to transform of the form y = x op c1
540       * @param def
541       *          the definition of x, the defining instruction is of the form x = a
542       *          op c2
543       * @return the new instruction to replace s;
544       */
545      private static Instruction transform(Instruction s, Instruction def) {
546        // x = a op1 c1  <-- def
547        // y = x op2 c2  <-- s
548        final RegisterOperand a = getUseFromCandidate(def);
549        final RegisterOperand x = getDefFromCandidate(def, true);
550        if (x == null) {
551          return null;
552        }
553        final RegisterOperand y = getDefFromCandidate(s, false);
554        if (y == null) {
555          return null;
556        }
557    
558        if (VM.VerifyAssertions) {
559          RegisterOperand x2;
560          x2 = getUseFromCandidate(s);
561          VM._assert(x.similar(x2), "x not similar to x2 " + x + " : " + x2);
562        }
563    
564        switch (s.operator.opcode) {
565          // Foldable operators
566          case INT_ADD_opcode: {
567            if (FOLD_INTS && FOLD_ADDS) {
568              int c2 = getIntValue(Binary.getVal2(s));
569              if (def.operator == INT_ADD) {
570                int c1 = getIntValue(Binary.getVal2(def));
571                // x = a + c1; y = x + c2
572                return Binary.create(INT_ADD, y.copyRO(), a.copyRO(), IC(c1 + c2));
573              } else if (def.operator == INT_SUB) {
574                int c1 = getIntValue(Binary.getVal2(def));
575                // x = a - c1; y = x + c2
576                return Binary.create(INT_ADD, y.copyRO(), a.copyRO(), IC(c2 - c1));
577              } else if (def.operator == INT_NEG && FOLD_CONSTANTS_TO_LHS) {
578                // x = -a; y = x + c2;
579                return Binary.create(INT_SUB, y.copyRO(), IC(c2), a.copyRO());
580              }
581            }
582            return null;
583          }
584          case REF_ADD_opcode: {
585            if (FOLD_REFS && FOLD_ADDS) {
586              Address c2 = getAddressValue(Binary.getVal2(s));
587              if (def.operator == REF_ADD) {
588                Address c1 = getAddressValue(Binary.getVal2(def));
589                // x = a + c1; y = x + c2
590                return Binary.create(REF_ADD, y.copyRO(), a.copyRO(), AC(c1.toWord().plus(c2.toWord()).toAddress()));
591              } else if (def.operator == REF_SUB) {
592                Address c1 = getAddressValue(Binary.getVal2(def));
593                // x = a - c1; y = x + c2
594                return Binary.create(REF_ADD, y.copyRO(), a.copyRO(), AC(c2.toWord().minus(c1.toWord()).toAddress()));
595              } else if (def.operator == REF_NEG && FOLD_CONSTANTS_TO_LHS) {
596                // x = -a; y = x + c2;
597                return Binary.create(REF_SUB, y.copyRO(), AC(c2), a.copyRO());
598              }
599            }
600            return null;
601          }
602          case LONG_ADD_opcode: {
603            if (FOLD_LONGS && FOLD_ADDS) {
604              long c2 = getLongValue(Binary.getVal2(s));
605              if (def.operator == LONG_ADD) {
606                long c1 = getLongValue(Binary.getVal2(def));
607                // x = a + c1; y = x + c2
608                return Binary.create(LONG_ADD, y.copyRO(), a.copyRO(), LC(c1 + c2));
609              } else if (def.operator == LONG_SUB) {
610                long c1 = getLongValue(Binary.getVal2(def));
611                // x = a - c1; y = x + c2
612                return Binary.create(LONG_ADD, y.copyRO(), a.copyRO(), LC(c2 - c1));
613              } else if (def.operator == LONG_NEG && FOLD_CONSTANTS_TO_LHS) {
614                // x = -a; y = x + c2;
615                return Binary.create(LONG_SUB, y.copyRO(), LC(c2), a.copyRO());
616              }
617            }
618            return null;
619          }
620          case FLOAT_ADD_opcode: {
621            if (FOLD_FLOATS && FOLD_ADDS) {
622              float c2 = getFloatValue(Binary.getVal2(s));
623              if (def.operator == FLOAT_ADD) {
624                float c1 = getFloatValue(Binary.getVal2(def));
625                // x = a + c1; y = x + c2
626                return Binary.create(FLOAT_ADD, y.copyRO(), a.copyRO(), FC(c1 + c2));
627              } else if (def.operator == FLOAT_SUB) {
628                float c1 = getFloatValue(Binary.getVal2(def));
629                // x = a - c1; y = x + c2
630                return Binary.create(FLOAT_ADD, y.copyRO(), a.copyRO(), FC(c2 - c1));
631              } else if (def.operator == FLOAT_NEG && FOLD_CONSTANTS_TO_LHS) {
632                // x = -a; y = x + c2;
633                return Binary.create(FLOAT_SUB, y.copyRO(), FC(c2), a.copyRO());
634              }
635            }
636            return null;
637          }
638          case DOUBLE_ADD_opcode: {
639            if (FOLD_DOUBLES && FOLD_ADDS) {
640              double c2 = getDoubleValue(Binary.getVal2(s));
641              if (def.operator == DOUBLE_ADD) {
642                double c1 = getDoubleValue(Binary.getVal2(def));
643                // x = a + c1; y = x + c2
644                return Binary.create(DOUBLE_ADD, y.copyRO(), a.copyRO(), DC(c1 + c2));
645              } else if (def.operator == DOUBLE_SUB) {
646                double c1 = getDoubleValue(Binary.getVal2(def));
647                // x = a - c1; y = x + c2
648                return Binary.create(DOUBLE_ADD, y.copyRO(), a.copyRO(), DC(c2 - c1));
649              } else if (def.operator == DOUBLE_NEG && FOLD_CONSTANTS_TO_LHS) {
650                // x = -a; y = x + c2;
651                return Binary.create(DOUBLE_SUB, y.copyRO(), DC(c2), a.copyRO());
652              }
653            }
654            return null;
655          }
656          case INT_SUB_opcode: {
657            if (FOLD_INTS && FOLD_SUBS) {
658              int c2 = getIntValue(Binary.getVal2(s));
659              if (def.operator == INT_ADD) {
660                int c1 = getIntValue(Binary.getVal2(def));
661                // x = a + c1; y = x - c2
662                return Binary.create(INT_ADD, y.copyRO(), a.copyRO(), IC(c1 - c2));
663              } else if (def.operator == INT_SUB) {
664                int c1 = getIntValue(Binary.getVal2(def));
665                // x = a - c1; y = x - c2
666                return Binary.create(INT_ADD, y.copyRO(), a.copyRO(), IC(-c1 - c2));
667              } else if (def.operator == INT_NEG && FOLD_CONSTANTS_TO_LHS) {
668                // x = -a; y = x - c2;
669                return Binary.create(INT_SUB, y.copyRO(), IC(-c2), a.copyRO());
670              }
671            }
672            return null;
673          }
674          case REF_SUB_opcode: {
675            if (FOLD_REFS && FOLD_SUBS) {
676              Address c2 = getAddressValue(Binary.getVal2(s));
677              if (def.operator == REF_ADD) {
678                Address c1 = getAddressValue(Binary.getVal2(def));
679                // x = a + c1; y = x - c2
680                return Binary.create(REF_ADD, y.copyRO(), a.copyRO(), AC(c1.toWord().minus(c2.toWord()).toAddress()));
681              } else if (def.operator == REF_SUB) {
682                Address c1 = getAddressValue(Binary.getVal2(def));
683                // x = a - c1; y = x - c2
684                return Binary.create(REF_ADD,
685                                     y.copyRO(),
686                                     a.copyRO(),
687                                     AC(Word.zero().minus(c1.toWord()).minus(c2.toWord()).toAddress()));
688              } else if (def.operator == REF_NEG && FOLD_CONSTANTS_TO_LHS) {
689                // x = -a; y = x - c2;
690                return Binary.create(REF_SUB, y.copyRO(), AC(Word.zero().minus(c2.toWord()).toAddress()), a.copyRO());
691              }
692            }
693            return null;
694          }
695          case LONG_SUB_opcode: {
696            if (FOLD_LONGS && FOLD_SUBS) {
697              long c2 = getLongValue(Binary.getVal2(s));
698              if (def.operator == LONG_ADD) {
699                long c1 = getLongValue(Binary.getVal2(def));
700                // x = a + c1; y = x - c2
701                return Binary.create(LONG_ADD, y.copyRO(), a.copyRO(), LC(c1 - c2));
702              } else if (def.operator == LONG_SUB) {
703                long c1 = getLongValue(Binary.getVal2(def));
704                // x = a - c1; y = x - c2
705                return Binary.create(LONG_ADD, y.copyRO(), a.copyRO(), LC(-c1 - c2));
706              } else if (def.operator == LONG_NEG && FOLD_CONSTANTS_TO_LHS) {
707                // x = -a; y = x - c2;
708                return Binary.create(LONG_SUB, y.copyRO(), LC(-c2), a.copyRO());
709              }
710            }
711            return null;
712          }
713          case FLOAT_SUB_opcode: {
714            if (FOLD_FLOATS && FOLD_SUBS) {
715              float c2 = getFloatValue(Binary.getVal2(s));
716              if (def.operator == FLOAT_ADD) {
717                float c1 = getFloatValue(Binary.getVal2(def));
718                // x = a + c1; y = x - c2
719                return Binary.create(FLOAT_ADD, y.copyRO(), a.copyRO(), FC(c1 - c2));
720              } else if (def.operator == FLOAT_SUB) {
721                float c1 = getFloatValue(Binary.getVal2(def));
722                // x = a - c1; y = x - c2
723                return Binary.create(FLOAT_ADD, y.copyRO(), a.copyRO(), FC(-c1 - c2));
724              } else if (def.operator == FLOAT_NEG && FOLD_CONSTANTS_TO_LHS) {
725                // x = -a; y = x - c2;
726                return Binary.create(FLOAT_SUB, y.copyRO(), FC(-c2), a.copyRO());
727              }
728            }
729            return null;
730          }
731          case DOUBLE_SUB_opcode: {
732            if (FOLD_DOUBLES && FOLD_SUBS) {
733              double c2 = getDoubleValue(Binary.getVal2(s));
734              if (def.operator == FLOAT_ADD) {
735                double c1 = getDoubleValue(Binary.getVal2(def));
736                // x = a + c1; y = x - c2
737                return Binary.create(DOUBLE_ADD, y.copyRO(), a.copyRO(), DC(c1 - c2));
738              } else if (def.operator == DOUBLE_SUB) {
739                double c1 = getDoubleValue(Binary.getVal2(def));
740                // x = a - c1; y = x + c2
741                return Binary.create(DOUBLE_ADD, y.copyRO(), a.copyRO(), DC(-c1 - c2));
742              } else if (def.operator == DOUBLE_NEG && FOLD_CONSTANTS_TO_LHS) {
743                // x = -a; y = x - c2;
744                return Binary.create(DOUBLE_SUB, y.copyRO(), DC(-c2), a.copyRO());
745              }
746            }
747            return null;
748          }
749          case INT_MUL_opcode: {
750            if (FOLD_INTS && FOLD_MULTS) {
751              int c2 = getIntValue(Binary.getVal2(s));
752              if (def.operator == INT_MUL) {
753                int c1 = getIntValue(Binary.getVal2(def));
754                // x = a * c1; y = x * c2
755                return Binary.create(INT_MUL, y.copyRO(), a.copyRO(), IC(c1 * c2));
756              } else if (def.operator == INT_NEG) {
757                // x = -a; y = x * c2;
758                return Binary.create(INT_MUL, y.copyRO(), a.copyRO(), IC(-c2));
759              }
760            }
761            return null;
762          }
763          case LONG_MUL_opcode: {
764            if (FOLD_LONGS && FOLD_MULTS) {
765              long c2 = getLongValue(Binary.getVal2(s));
766              if (def.operator == LONG_MUL) {
767                long c1 = getLongValue(Binary.getVal2(def));
768                // x = a * c1; y = x * c2
769                return Binary.create(LONG_MUL, y.copyRO(), a.copyRO(), LC(c1 * c2));
770              } else if (def.operator == LONG_NEG) {
771                // x = -a; y = x * c2;
772                return Binary.create(LONG_MUL, y.copyRO(), a.copyRO(), LC(-c2));
773              }
774            }
775            return null;
776          }
777          case FLOAT_MUL_opcode: {
778            if (FOLD_FLOATS && FOLD_MULTS) {
779              float c2 = getFloatValue(Binary.getVal2(s));
780              if (def.operator == FLOAT_MUL) {
781                float c1 = getFloatValue(Binary.getVal2(def));
782                // x = a * c1; y = x * c2
783                return Binary.create(FLOAT_MUL, y.copyRO(), a.copyRO(), FC(c1 * c2));
784              } else if (def.operator == FLOAT_NEG) {
785                // x = -a; y = x * c2;
786                return Binary.create(FLOAT_MUL, y.copyRO(), a.copyRO(), FC(-c2));
787              }
788            }
789            return null;
790          }
791          case DOUBLE_MUL_opcode: {
792            if (FOLD_DOUBLES && FOLD_MULTS) {
793              double c2 = getDoubleValue(Binary.getVal2(s));
794              if (def.operator == DOUBLE_MUL) {
795                double c1 = getDoubleValue(Binary.getVal2(def));
796                // x = a * c1; y = x * c2
797                return Binary.create(DOUBLE_MUL, y.copyRO(), a.copyRO(), DC(c1 * c2));
798              } else if (def.operator == DOUBLE_NEG) {
799                // x = -a; y = x * c2;
800                return Binary.create(DOUBLE_MUL, y.copyRO(), a.copyRO(), DC(-c2));
801              }
802            }
803            return null;
804          }
805          case INT_DIV_opcode: {
806            if (FOLD_INTS && FOLD_DIVS) {
807              int c2 = getIntValue(GuardedBinary.getVal2(s));
808              if (def.operator == INT_DIV) {
809                int c1 = getIntValue(GuardedBinary.getVal2(def));
810                Operand guard = GuardedBinary.getGuard(def);
811                // x = a / c1; y = x / c2
812                return GuardedBinary.create(INT_DIV, y.copyRO(), a.copyRO(), IC(c1 * c2), guard);
813              } else if (def.operator == INT_NEG) {
814                Operand guard = GuardedBinary.getGuard(s);
815                // x = -a; y = x / c2;
816                return GuardedBinary.create(INT_DIV, y.copyRO(), a.copyRO(), IC(-c2), guard);
817              }
818            }
819            return null;
820          }
821          case LONG_DIV_opcode: {
822            if (FOLD_LONGS && FOLD_DIVS) {
823              long c2 = getLongValue(GuardedBinary.getVal2(s));
824              if (def.operator == LONG_DIV) {
825                long c1 = getLongValue(GuardedBinary.getVal2(def));
826                Operand guard = GuardedBinary.getGuard(def);
827                // x = a / c1; y = x / c2
828                return GuardedBinary.create(LONG_DIV, y.copyRO(), a.copyRO(), LC(c1 * c2), guard);
829              } else if (def.operator == LONG_NEG) {
830                Operand guard = GuardedBinary.getGuard(s);
831                // x = -a; y = x / c2;
832                return GuardedBinary.create(LONG_DIV, y.copyRO(), a.copyRO(), LC(-c2), guard);
833              }
834            }
835            return null;
836          }
837          case FLOAT_DIV_opcode: {
838            if (FOLD_FLOATS && FOLD_DIVS) {
839              float c2 = getFloatValue(Binary.getVal2(s));
840              if (def.operator == FLOAT_DIV) {
841                float c1 = getFloatValue(Binary.getVal2(def));
842                // x = a / c1; y = x / c2
843                return Binary.create(FLOAT_DIV, y.copyRO(), a.copyRO(), FC(c1 * c2));
844              } else if (def.operator == FLOAT_NEG) {
845                // x = -a; y = x / c2;
846                return Binary.create(FLOAT_DIV, y.copyRO(), a.copyRO(), FC(-c2));
847              }
848            }
849            return null;
850          }
851          case DOUBLE_DIV_opcode: {
852            if (FOLD_DOUBLES && FOLD_DIVS) {
853              double c2 = getDoubleValue(Binary.getVal2(s));
854              if (def.operator == DOUBLE_DIV) {
855                double c1 = getDoubleValue(Binary.getVal2(def));
856                // x = a / c1; y = x / c2
857                return Binary.create(DOUBLE_DIV, y.copyRO(), a.copyRO(), DC(c1 * c2));
858              } else if (def.operator == DOUBLE_NEG) {
859                // x = -a; y = x / c2;
860                return Binary.create(DOUBLE_DIV, y.copyRO(), a.copyRO(), DC(-c2));
861              }
862            }
863            return null;
864          }
865          case INT_SHL_opcode: {
866            if (FOLD_INTS && FOLD_SHIFTLS) {
867              int c2 = getIntValue(Binary.getVal2(s));
868              if (def.operator == INT_SHL) {
869                int c1 = getIntValue(Binary.getVal2(def));
870                // x = a << c1; y = x << c2
871                return Binary.create(INT_SHL, y.copyRO(), a.copyRO(), IC(c1 + c2));
872              } else if ((def.operator == INT_SHR) || (def.operator == INT_USHR)) {
873                int c1 = getIntValue(Binary.getVal2(def));
874                if (c1 == c2) {
875                  // x = a >> c1; y = x << c1
876                  return Binary.create(INT_AND, y.copyRO(), a.copyRO(), IC(-1 << c1));
877                }
878              } else if (def.operator == INT_AND) {
879                int c1 = getIntValue(Binary.getVal2(def));
880                // x = a & c1; y = << c2
881                if ((c1 << c2) == (-1 << c2)) {
882                  // the first mask is redundant
883                  return Binary.create(INT_SHL, y.copyRO(), a.copyRO(), IC(c2));
884                }
885              } else if ((def.operator == INT_OR)||(def.operator == INT_XOR)) {
886                int c1 = getIntValue(Binary.getVal2(def));
887                // x = a | c1; y = << c2
888                if ((c1 << c2) == 0) {
889                  // the first mask is redundant
890                  return Binary.create(INT_SHL, y.copyRO(), a.copyRO(), IC(c2));
891                }
892              }
893            }
894            return null;
895          }
896          case REF_SHL_opcode: {
897            if (FOLD_REFS && FOLD_SHIFTLS) {
898              int c2 = getIntValue(Binary.getVal2(s));
899              if (def.operator == REF_SHL) {
900                int c1 = getIntValue(Binary.getVal2(def));
901                // x = a << c1; y = x << c2
902                return Binary.create(REF_SHL, y.copyRO(), a.copyRO(), IC(c1 + c2));
903              } else if ((def.operator == REF_SHR) || (def.operator == REF_USHR)) {
904                int c1 = getIntValue(Binary.getVal2(def));
905                if (c1 == c2) {
906                  // x = a >> c1; y = x << c1
907                  return Binary.create(REF_AND,
908                                       y.copyRO(),
909                                       a.copyRO(),
910                                       AC(Word.zero().minus(Word.one()).lsh(c1).toAddress()));
911                }
912              } else if (def.operator == REF_AND) {
913                Address c1 = getAddressValue(Binary.getVal2(def));
914                // x = a & c1; y = x << c2
915                if (c1.toWord().lsh(c2).EQ(Word.fromIntSignExtend(-1).lsh(c2))) {
916                  // the first mask is redundant
917                  return Binary.create(REF_SHL, y.copyRO(), a.copyRO(), IC(c2));
918                }
919              } else if ((def.operator == REF_OR)||(def.operator == REF_XOR)) {
920                Address c1 = getAddressValue(Binary.getVal2(def));
921                // x = a | c1; y = x << c2
922                if (c1.toWord().lsh(c2).EQ(Word.zero())) {
923                  // the first mask is redundant
924                  return Binary.create(REF_SHL, y.copyRO(), a.copyRO(), IC(c2));
925                }
926              }
927            }
928            return null;
929          }
930          case LONG_SHL_opcode: {
931            if (FOLD_LONGS && FOLD_SHIFTLS) {
932              int c2 = getIntValue(Binary.getVal2(s));
933              if (def.operator == LONG_SHL) {
934                int c1 = getIntValue(Binary.getVal2(def));
935                // x = a << c1; y = x << c2
936                return Binary.create(LONG_SHL, y.copyRO(), a.copyRO(), IC(c1 + c2));
937              } else if ((def.operator == LONG_SHR) || (def.operator == LONG_USHR)) {
938                int c1 = getIntValue(Binary.getVal2(def));
939                if (c1 == c2) {
940                  // x = a >> c1; y = x << c1
941                  return Binary.create(LONG_AND, y.copyRO(), a.copyRO(), LC(-1L << c1));
942                }
943              } else if (def.operator == LONG_AND) {
944                long c1 = getLongValue(Binary.getVal2(def));
945                // x = a & c1; y = << c2
946                if ((c1 << c2) == (-1L << c2)) {
947                  // the first mask is redundant
948                  return Binary.create(LONG_SHL, y.copyRO(), a.copyRO(), IC(c2));
949                }
950              } else if ((def.operator == LONG_OR)||(def.operator == LONG_XOR)) {
951                long c1 = getLongValue(Binary.getVal2(def));
952                // x = a | c1; y = << c2
953                if ((c1 << c2) == 0L) {
954                  // the first mask is redundant
955                  return Binary.create(LONG_SHL, y.copyRO(), a.copyRO(), IC(c2));
956                }
957              }
958            }
959            return null;
960          }
961          case INT_SHR_opcode: {
962            if (FOLD_INTS && FOLD_SHIFTRS) {
963              int c2 = getIntValue(Binary.getVal2(s));
964              if (def.operator == INT_SHR) {
965                int c1 = getIntValue(Binary.getVal2(def));
966                // x = a >> c1; y = x >> c2
967                return Binary.create(INT_SHR, y.copyRO(), a.copyRO(), IC(c1 + c2));
968              } else if (def.operator == INT_SHL) {
969                int c1 = getIntValue(Binary.getVal2(def));
970                if (c1 == c2) {
971                  if (c1 == 24) {
972                    // x = a << 24; y = x >> 24
973                    return Unary.create(INT_2BYTE, y.copyRO(), a.copyRO());
974                  } else if (c1 == 16) {
975                    // x = a << 16; y = x >> 16
976                    return Unary.create(INT_2SHORT, y.copyRO(), a.copyRO());
977                  }
978                }
979              } else if (def.operator == INT_AND) {
980                int c1 = getIntValue(Binary.getVal2(def));
981                // x = a & c1; y = >> c2
982                if ((c1 >> c2) == -1) {
983                  // the first mask is redundant
984                  return Binary.create(INT_SHR, y.copyRO(), a.copyRO(), IC(c2));
985                }
986              } else if ((def.operator == INT_OR)||(def.operator == INT_XOR)) {
987                int c1 = getIntValue(Binary.getVal2(def));
988                // x = a | c1; y = >> c2
989                if ((c1 >>> c2) == 0) {
990                  // the first mask is redundant
991                  return Binary.create(INT_SHR, y.copyRO(), a.copyRO(), IC(c2));
992                }
993              }
994            }
995            return null;
996          }
997          case REF_SHR_opcode: {
998            if (FOLD_REFS && FOLD_SHIFTRS) {
999              int c2 = getIntValue(Binary.getVal2(s));
1000              if (def.operator == REF_SHR) {
1001                int c1 = getIntValue(Binary.getVal2(def));
1002                // x = a >> c1; y = x >> c2
1003                return Binary.create(REF_SHR, y.copyRO(), a.copyRO(), IC(c1 + c2));
1004              } else if (def.operator == REF_AND) {
1005                Address c1 = getAddressValue(Binary.getVal2(def));
1006                // x = a & c1; y = x >> c2
1007                if (c1.toWord().rsha(c2).EQ(Word.zero().minus(Word.one()))) {
1008                  // the first mask is redundant
1009                  return Binary.create(REF_SHR, y.copyRO(), a.copyRO(), IC(c2));
1010                }
1011              } else if ((def.operator == REF_OR)||(def.operator == REF_XOR)) {
1012                Address c1 = getAddressValue(Binary.getVal2(def));
1013                // x = a | c1; y = x >> c2
1014                if (c1.toWord().rshl(c2).EQ(Word.zero())) {
1015                  // the first mask is redundant
1016                  return Binary.create(REF_SHR, y.copyRO(), a.copyRO(), IC(c2));
1017                }
1018              }
1019            }
1020            return null;
1021          }
1022          case LONG_SHR_opcode: {
1023            if (FOLD_LONGS && FOLD_SHIFTRS) {
1024              int c2 = getIntValue(Binary.getVal2(s));
1025              if (def.operator == LONG_SHR) {
1026                int c1 = getIntValue(Binary.getVal2(def));
1027                // x = a >> c1; y = x >> c2
1028                return Binary.create(LONG_SHR, y.copyRO(), a.copyRO(), IC(c1 + c2));
1029              } else if (def.operator == LONG_AND) {
1030                long c1 = getLongValue(Binary.getVal2(def));
1031                // x = a & c1; y = >> c2
1032                if ((c1 >> c2) == -1L) {
1033                  // the first mask is redundant
1034                  return Binary.create(LONG_SHR, y.copyRO(), a.copyRO(), IC(c2));
1035                }
1036              } else if ((def.operator == LONG_OR)||(def.operator == LONG_XOR)) {
1037                long c1 = getLongValue(Binary.getVal2(def));
1038                // x = a & c1; y = >> c2
1039                if ((c1 >>> c2) == 0L) {
1040                  // the first mask is redundant
1041                  return Binary.create(LONG_SHR, y.copyRO(), a.copyRO(), IC(c2));
1042                }
1043              }
1044            }
1045            return null;
1046          }
1047          case INT_USHR_opcode: {
1048            if (FOLD_INTS && FOLD_SHIFTRS) {
1049              int c2 = getIntValue(Binary.getVal2(s));
1050              if (def.operator == INT_USHR) {
1051                int c1 = getIntValue(Binary.getVal2(def));
1052                // x = a >>> c1; y = x >>> c2
1053                return Binary.create(INT_USHR, y.copyRO(), a.copyRO(), IC(c1 + c2));
1054              } else if (def.operator == INT_SHL) {
1055                int c1 = getIntValue(Binary.getVal2(def));
1056                if (c1 == c2) {
1057                  // x = a << c1; y = x >>> c1
1058                  return Binary.create(INT_AND, y.copyRO(), a.copyRO(), IC(-1 >>> c1));
1059                }
1060              } else if (def.operator == INT_AND) {
1061                int c1 = getIntValue(Binary.getVal2(def));
1062                // x = a & c1; y = >>> c2
1063                if ((c1 >> c2) == -1L) {
1064                  // the first mask is redundant
1065                  return Binary.create(INT_USHR, y.copyRO(), a.copyRO(), IC(c2));
1066                }
1067              } else if ((def.operator == INT_OR)||(def.operator == INT_XOR)) {
1068                int c1 = getIntValue(Binary.getVal2(def));
1069                // x = a | c1; y = >>> c2
1070                if ((c1 >>> c2) == 0) {
1071                  // the first mask is redundant
1072                  return Binary.create(INT_USHR, y.copyRO(), a.copyRO(), IC(c2));
1073                }
1074              }
1075            }
1076            return null;
1077          }
1078          case REF_USHR_opcode: {
1079            if (FOLD_REFS && FOLD_SHIFTRS) {
1080              int c2 = getIntValue(Binary.getVal2(s));
1081              if (def.operator == REF_USHR) {
1082                int c1 = getIntValue(Binary.getVal2(def));
1083                // x = a >>> c1; y = x >>> c2
1084                return Binary.create(REF_USHR, y.copyRO(), a.copyRO(), IC(c1 + c2));
1085              } else if (def.operator == REF_SHL) {
1086                int c1 = getIntValue(Binary.getVal2(def));
1087                if (c1 == c2) {
1088                  // x = a << c1; y = x >>> c1
1089                  return Binary.create(REF_AND,
1090                                       y.copyRO(),
1091                                       a.copyRO(),
1092                                       AC(Word.zero().minus(Word.one()).rshl(c1).toAddress()));
1093                }
1094              } else if (def.operator == REF_AND) { //IAN!!!
1095                Address c1 = getAddressValue(Binary.getVal2(def));
1096                // x = a & c1; y = x >>> c2
1097                if (c1.toWord().rsha(c2).EQ(Word.zero().minus(Word.one()))) {
1098                  // the first mask is redundant
1099                  return Binary.create(REF_USHR, y.copyRO(), a.copyRO(), IC(c2));
1100                }
1101              } else if (false) { //(def.operator == REF_OR)||(def.operator == REF_XOR)) {
1102                Address c1 = getAddressValue(Binary.getVal2(def));
1103                // x = a | c1; y = x >>> c2
1104                if (c1.toWord().rshl(c2).EQ(Word.zero())) {
1105                  // the first mask is redundant
1106                  return Binary.create(REF_USHR, y.copyRO(), a.copyRO(), IC(c2));
1107                }
1108              }
1109            }
1110            return null;
1111          }
1112          case LONG_USHR_opcode: {
1113            if (FOLD_LONGS && FOLD_SHIFTRS) {
1114              int c2 = getIntValue(Binary.getVal2(s));
1115              if (def.operator == LONG_USHR) {
1116                int c1 = getIntValue(Binary.getVal2(def));
1117                // x = a >>> c1; y = x >>> c2
1118                return Binary.create(LONG_USHR, y.copyRO(), a.copyRO(), IC(c1 + c2));
1119              } else if (def.operator == LONG_SHL) {
1120                int c1 = getIntValue(Binary.getVal2(def));
1121                if (c1 == c2) {
1122                  // x = a << c1; y = x >>> c1
1123                  return Binary.create(LONG_AND, y.copyRO(), a.copyRO(), LC(-1L >>> c1));
1124                }
1125              } else if (def.operator == LONG_AND) {
1126                long c1 = getLongValue(Binary.getVal2(def));
1127                // x = a & c1; y = >>> c2
1128                if ((c1 >> c2) == -1L) {
1129                  // the first mask is redundant
1130                  return Binary.create(LONG_USHR, y.copyRO(), a.copyRO(), IC(c2));
1131                }
1132              } else if ((def.operator == LONG_OR)||(def.operator == LONG_XOR)) {
1133                long c1 = getLongValue(Binary.getVal2(def));
1134                // x = a & c1; y = >>> c2
1135                if ((c1 >>> c2) == 0L) {
1136                  // the first mask is redundant
1137                  return Binary.create(LONG_USHR, y.copyRO(), a.copyRO(), IC(c2));
1138                }
1139              }
1140            }
1141            return null;
1142          }
1143          case INT_AND_opcode: {
1144            if (FOLD_INTS && FOLD_ANDS) {
1145              int c2 = getIntValue(Binary.getVal2(s));
1146              if (def.operator == INT_AND) {
1147                int c1 = getIntValue(Binary.getVal2(def));
1148                // x = a & c1; y = x & c2
1149                return Binary.create(INT_AND, y.copyRO(), a.copyRO(), IC(c1 & c2));
1150              } else if (def.operator == INT_OR) {
1151                int c1 = getIntValue(Binary.getVal2(def));
1152                // x = a | c1; y = x & c2
1153                if ((c1 & c2) == 0) {
1154                  return Binary.create(INT_AND, y.copyRO(), a.copyRO(), IC(c2));
1155                }
1156              } else if (def.operator == INT_XOR) {
1157                int c1 = getIntValue(Binary.getVal2(def));
1158                // x = a ^ c1; y = x & c2
1159                if ((c1 & c2) == 0) {
1160                  return Binary.create(INT_AND, y.copyRO(), a.copyRO(), IC(c2));
1161                }
1162              } else if (def.operator == INT_SHR) {
1163                int c1 = getIntValue(Binary.getVal2(def));
1164                // x = a >> c1; y = x & c2
1165                if ((-1 >>> c1) == c2) {
1166                  // turn arithmetic shifts into logical shifts if possible
1167                  return Binary.create(INT_USHR, y.copyRO(), a.copyRO(), IC(c1));
1168                }
1169              } else if (def.operator == INT_SHL) {
1170                int c1 = getIntValue(Binary.getVal2(def));
1171                // x = a << c1; y = x & c2
1172                if (((-1 << c1) & c2) == (-1 << c1)) {
1173                  // does the mask zero bits already cleared by the shift?
1174                  return Binary.create(INT_SHL, y.copyRO(), a.copyRO(), IC(c1));
1175                }
1176              } else if (def.operator == INT_USHR) {
1177                int c1 = getIntValue(Binary.getVal2(def));
1178                // x = a >>> c1; y = x & c2
1179                if (((-1 >>> c1) & c2) == (-1 >>> c1)) {
1180                  // does the mask zero bits already cleared by the shift?
1181                  return Binary.create(INT_USHR, y.copyRO(), a.copyRO(), IC(c1));
1182                }
1183              }
1184            }
1185            return null;
1186          }
1187          case REF_AND_opcode: {
1188            if (FOLD_REFS && FOLD_ANDS) {
1189              Address c2 = getAddressValue(Binary.getVal2(s));
1190              if (def.operator == REF_AND) {
1191                Address c1 = getAddressValue(Binary.getVal2(def));
1192                // x = a & c1; y = x & c2
1193                return Binary.create(REF_AND, y.copyRO(), a.copyRO(), AC(c1.toWord().and(c2.toWord()).toAddress()));
1194              } else if (def.operator == REF_OR) {
1195                Address c1 = getAddressValue(Binary.getVal2(def));
1196                // x = a | c1; y = x & c2
1197                if (c1.toWord().and(c2.toWord()).EQ(Word.zero())) {
1198                  return Binary.create(REF_AND, y.copyRO(), a.copyRO(), AC(c2));
1199                }
1200              } else if (def.operator == REF_XOR) {
1201                Address c1 = getAddressValue(Binary.getVal2(def));
1202                // x = a ^ c1; y = x & c2
1203                if (c1.toWord().and(c2.toWord()).EQ(Word.zero())) {
1204                  return Binary.create(REF_AND, y.copyRO(), a.copyRO(), AC(c2));
1205                }
1206              } else if (def.operator == REF_SHR) {
1207                int c1 = getIntValue(Binary.getVal2(def));
1208                // x = a >> c1; y = x & c2
1209                if (Word.zero().minus(Word.one()).rshl(c1).toAddress().EQ(c2)) {
1210                  // turn arithmetic shifts into logical ones if possible
1211                  return Binary.create(REF_USHR, y.copyRO(), a.copyRO(), IC(c1));
1212                }
1213              } else if (def.operator == REF_SHL) {
1214                int c1 = getIntValue(Binary.getVal2(def));
1215                // x = a << c1; y = x & c2
1216                if (Word.zero().minus(Word.one()).lsh(c1).and(c2.toWord()).EQ(Word.zero().minus(Word.one()).lsh(c1))) {
1217                  // does the mask zero bits already cleared by the shift?
1218                  return Binary.create(REF_SHL, y.copyRO(), a.copyRO(), IC(c1));
1219                }
1220              } else if (def.operator == REF_USHR) {
1221                int c1 = getIntValue(Binary.getVal2(def));
1222                // x = a >>> c1; y = x & c2
1223                if (Word.zero().minus(Word.one()).rshl(c1).and(c2.toWord()).EQ(Word.zero().minus(Word.one()).rshl(c1))) {
1224                  // does the mask zero bits already cleared by the shift?
1225                  return Binary.create(REF_USHR, y.copyRO(), a.copyRO(), IC(c1));
1226                }
1227              }
1228            }
1229            return null;
1230          }
1231          case LONG_AND_opcode: {
1232            if (FOLD_LONGS && FOLD_ANDS) {
1233              long c2 = getLongValue(Binary.getVal2(s));
1234              if (def.operator == LONG_AND) {
1235                long c1 = getLongValue(Binary.getVal2(def));
1236                // x = a & c1; y = x & c2
1237                return Binary.create(LONG_AND, y.copyRO(), a.copyRO(), LC(c1 & c2));
1238              } else if (def.operator == LONG_OR) {
1239                long c1 = getLongValue(Binary.getVal2(def));
1240                // x = a | c1; y = x & c2
1241                if ((c1 & c2) == 0) {
1242                  return Binary.create(LONG_AND, y.copyRO(), a.copyRO(), LC(c2));
1243                }
1244              } else if (def.operator == LONG_XOR) {
1245                long c1 = getLongValue(Binary.getVal2(def));
1246                // x = a ^ c1; y = x & c2
1247                if ((c1 & c2) == 0) {
1248                  return Binary.create(LONG_AND, y.copyRO(), a.copyRO(), LC(c2));
1249                }
1250              } else if (def.operator == LONG_SHR) {
1251                int c1 = getIntValue(Binary.getVal2(def));
1252                // x = a >> c1; y = x & c2
1253                if ((-1L >>> c1) == c2) {
1254                  // turn arithmetic shifts into logical ones if possible
1255                  return Binary.create(LONG_USHR, y.copyRO(), a.copyRO(), IC(c1));
1256                }
1257              } else if (def.operator == LONG_SHL) {
1258                int c1 = getIntValue(Binary.getVal2(def));
1259                // x = a << c1; y = x & c2
1260                if (((-1L << c1) & c2) == (-1L << c1)) {
1261                  // does the mask zero bits already cleared by the shift?
1262                  return Binary.create(LONG_SHL, y.copyRO(), a.copyRO(), IC(c1));
1263                }
1264              } else if (def.operator == LONG_USHR) {
1265                int c1 = getIntValue(Binary.getVal2(def));
1266                // x = a >>> c1; y = x & c2
1267                if (((-1L >>> c1) & c2) == (-1L >>> c1)) {
1268                  // does the mask zero bits already cleared by the shift?
1269                  return Binary.create(LONG_USHR, y.copyRO(), a.copyRO(), IC(c1));
1270                }
1271              }
1272            }
1273            return null;
1274          }
1275          case INT_OR_opcode: {
1276            if (FOLD_INTS && FOLD_ORS) {
1277              int c2 = getIntValue(Binary.getVal2(s));
1278              if (def.operator == INT_OR) {
1279                int c1 = getIntValue(Binary.getVal2(def));
1280                // x = a | c1; y = x | c2
1281                return Binary.create(INT_OR, y.copyRO(), a.copyRO(), IC(c1 | c2));
1282              } else if (def.operator == INT_AND) {
1283                int c1 = getIntValue(Binary.getVal2(def));
1284                // x = a & c1; y = x | c2
1285                if ((~c1 | c2) == c2) {
1286                  return Binary.create(INT_OR, y.copyRO(), a.copyRO(), IC(c2));
1287                }
1288              } else if (def.operator == INT_XOR) {
1289                int c1 = getIntValue(Binary.getVal2(def));
1290                // x = a ^ c1; y = x | c2
1291                if ((c1 | c2) == c2) {
1292                  return Binary.create(INT_OR, y.copyRO(), a.copyRO(), IC(c2));
1293                }
1294              }
1295            }
1296            return null;
1297          }
1298          case REF_OR_opcode: {
1299            if (FOLD_REFS && FOLD_ORS) {
1300              Address c2 = getAddressValue(Binary.getVal2(s));
1301              if (def.operator == REF_OR) {
1302                Address c1 = getAddressValue(Binary.getVal2(def));
1303                // x = a | c1; y = x | c2
1304                return Binary.create(REF_OR, y.copyRO(), a.copyRO(), AC(c1.toWord().or(c2.toWord()).toAddress()));
1305              } else if (def.operator == REF_AND) {
1306                Address c1 = getAddressValue(Binary.getVal2(def));
1307                // x = a & c1; y = x | c2
1308                if (c1.toWord().not().or(c2.toWord()).EQ(c2.toWord())) {
1309                  return Binary.create(REF_OR, y.copyRO(), a.copyRO(), AC(c2));
1310                }
1311              } else if (def.operator == REF_XOR) {
1312                Address c1 = getAddressValue(Binary.getVal2(def));
1313                // x = a ^ c1; y = x | c2
1314                if (c1.toWord().or(c2.toWord()).EQ(c2.toWord())) {
1315                  return Binary.create(REF_OR, y.copyRO(), a.copyRO(), AC(c2));
1316                }
1317              }
1318            }
1319            return null;
1320          }
1321          case LONG_OR_opcode: {
1322            if (FOLD_LONGS && FOLD_ORS) {
1323              long c2 = getLongValue(Binary.getVal2(s));
1324              if (def.operator == LONG_OR) {
1325                long c1 = getLongValue(Binary.getVal2(def));
1326                // x = a | c1; y = x | c2
1327                return Binary.create(LONG_OR, y.copyRO(), a.copyRO(), LC(c1 | c2));
1328              } else if (def.operator == LONG_AND) {
1329                long c1 = getLongValue(Binary.getVal2(def));
1330                // x = a & c1; y = x | c2
1331                if ((~c1 | c2) == c2) {
1332                  return Binary.create(LONG_OR, y.copyRO(), a.copyRO(), LC(c2));
1333                }
1334              } else if (def.operator == LONG_XOR) {
1335                long c1 = getLongValue(Binary.getVal2(def));
1336                // x = a ^ c1; y = x | c2
1337                if ((c1 | c2) == c2) {
1338                  return Binary.create(LONG_OR, y.copyRO(), a.copyRO(), LC(c2));
1339                }
1340              }
1341            }
1342            return null;
1343          }
1344          case INT_XOR_opcode: {
1345            if (FOLD_INTS && FOLD_XORS) {
1346              int c2 = getIntValue(Binary.getVal2(s));
1347              if (def.operator == INT_XOR) {
1348                int c1 = getIntValue(Binary.getVal2(def));
1349                // x = a ^ c1; y = x ^ c2
1350                return Binary.create(INT_XOR, y.copyRO(), a.copyRO(), IC(c1 ^ c2));
1351              } else if (def.operator == INT_NOT) {
1352                // x = ~a; y = x ^ c2
1353                return Binary.create(INT_XOR, y.copyRO(), a.copyRO(), IC(~c2));
1354              } else if (def.operator == BOOLEAN_NOT) {
1355                // x = !a; y = x ^ c2
1356                return Binary.create(INT_XOR, y.copyRO(), a.copyRO(), IC(c2 ^ 1));
1357              }
1358            }
1359            return null;
1360          }
1361          case REF_XOR_opcode: {
1362            if (FOLD_REFS && FOLD_XORS) {
1363              Address c2 = getAddressValue(Binary.getVal2(s));
1364              if (def.operator == REF_XOR) {
1365                Address c1 = getAddressValue(Binary.getVal2(def));
1366                // x = a ^ c1; y = x ^ c2
1367                return Binary.create(REF_XOR, y.copyRO(), a.copyRO(), AC(c1.toWord().xor(c2.toWord()).toAddress()));
1368              } else if (def.operator == REF_NOT) {
1369                // x = ~a; y = x ^ c2
1370                return Binary.create(REF_XOR, y.copyRO(), a.copyRO(), AC(c2.toWord().not().toAddress()));
1371              }
1372            }
1373            return null;
1374          }
1375          case LONG_XOR_opcode: {
1376            if (FOLD_LONGS && FOLD_XORS) {
1377              long c2 = getLongValue(Binary.getVal2(s));
1378              if (def.operator == LONG_XOR) {
1379                long c1 = getLongValue(Binary.getVal2(def));
1380                // x = a ^ c1; y = x ^ c2
1381                return Binary.create(LONG_XOR, y.copyRO(), a.copyRO(), LC(c1 ^ c2));
1382              } else if (def.operator == LONG_NOT) {
1383                // x = ~a; y = x ^ c2
1384                return Binary.create(LONG_XOR, y.copyRO(), a.copyRO(), LC(~c2));
1385              }
1386            }
1387            return null;
1388          }
1389          case LONG_CMP_opcode: {
1390            if (FOLD_LONGS && FOLD_CMPS) {
1391              long c2 = getLongValue(Binary.getVal2(s));
1392              if (def.operator == LONG_NEG) {
1393                // x = -a; y = x cmp c2
1394                return Binary.create(LONG_CMP, y.copyRO(), LC(-c2), a.copyRO());
1395              }
1396            }
1397            return null;
1398          }
1399          case FLOAT_CMPL_opcode:
1400          case FLOAT_CMPG_opcode: {
1401            if (FOLD_FLOATS && FOLD_CMPS) {
1402              float c2 = getFloatValue(Binary.getVal2(s));
1403              if (def.operator == FLOAT_ADD) {
1404                float c1 = getFloatValue(Binary.getVal2(def));
1405                // x = a + c1; y = x cmp c2
1406                return Binary.create(s.operator, y.copyRO(), a.copyRO(), FC(c2 - c1));
1407              } else if (def.operator == FLOAT_SUB) {
1408                float c1 = getFloatValue(Binary.getVal2(def));
1409                // x = a - c1; y = x cmp c2
1410                return Binary.create(s.operator, y.copyRO(), a.copyRO(), FC(c1 + c2));
1411              } else if (def.operator == FLOAT_NEG) {
1412                // x = -a; y = x cmp c2
1413                return Binary.create(s.operator, y.copyRO(), FC(-c2), a.copyRO());
1414              }
1415            }
1416            return null;
1417          }
1418          case DOUBLE_CMPL_opcode:
1419          case DOUBLE_CMPG_opcode: {
1420            if (FOLD_DOUBLES && FOLD_CMPS) {
1421              double c2 = getDoubleValue(Binary.getVal2(s));
1422              if (def.operator == DOUBLE_ADD) {
1423                double c1 = getDoubleValue(Binary.getVal2(def));
1424                // x = a + c1; y = x cmp c2
1425                return Binary.create(s.operator, y.copyRO(), a.copyRO(), DC(c2 - c1));
1426              } else if (def.operator == DOUBLE_SUB) {
1427                double c1 = getDoubleValue(Binary.getVal2(def));
1428                // x = a - c1; y = x cmp c2
1429                return Binary.create(s.operator, y.copyRO(), a.copyRO(), DC(c1 + c2));
1430              } else if (def.operator == DOUBLE_NEG) {
1431                // x = -a; y = x cmp c2
1432                return Binary.create(s.operator, y.copyRO(), DC(-c2), a.copyRO());
1433              }
1434            }
1435            return null;
1436          }
1437          case BOOLEAN_CMP_INT_opcode: {
1438            if (FOLD_INTS && FOLD_CMPS) {
1439              int c2 = getIntValue(BooleanCmp.getVal2(s));
1440              ConditionOperand cond = (ConditionOperand) BooleanCmp.getCond(s).copy();
1441              BranchProfileOperand prof = (BranchProfileOperand) BooleanCmp.getBranchProfile(s).copy();
1442              if (cond.isEQUAL() || cond.isNOT_EQUAL()) {
1443                if (def.operator == INT_ADD) {
1444                  int c1 = getIntValue(Binary.getVal2(def));
1445                  // x = a + c1; y = x cmp c2
1446                  return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), IC(c2 - c1), cond, prof);
1447                } else if (def.operator == INT_SUB) {
1448                  int c1 = getIntValue(Binary.getVal2(def));
1449                  // x = a - c1; y = x cmp c2
1450                  return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), IC(c1 + c2), cond, prof);
1451                } else if (def.operator == INT_NEG) {
1452                    // x = -a; y = x cmp c2
1453                    return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), IC(-c2), cond.flipOperands(), prof);
1454                } else if (def.operator == BOOLEAN_CMP_INT) {
1455                  int c1 = getIntValue(BooleanCmp.getVal2(def));
1456                  ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
1457                  // x = a cmp c1 ? true : false; y = x cmp c2 ? true : false
1458                  if ((cond.isEQUAL() && c2 == 1)||
1459                      (cond.isNOT_EQUAL() && c2 == 0)) {
1460                    // Fold away redundancy boolean_cmp
1461                    return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), IC(c1), cond2, prof);
1462                  } else if ((cond.isEQUAL() && c2 == 0)||
1463                      (cond.isNOT_EQUAL() && c2 == 1)) {
1464                    // Fold away redundancy boolean_cmp
1465                    return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), IC(c1), cond2.flipCode(), prof);
1466                  }
1467                } else if (def.operator == BOOLEAN_CMP_LONG) {
1468                  long c1 = getLongValue(BooleanCmp.getVal2(def));
1469                  ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
1470                  // x = a cmp c1 ? true : false; y = x cmp c2 ? true : false
1471                  if ((cond.isEQUAL() && c2 == 1)||
1472                      (cond.isNOT_EQUAL() && c2 == 0)) {
1473                    // Fold away redundancy boolean_cmp
1474                    return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), cond2, prof);
1475                  } else if ((cond.isEQUAL() && c2 == 0)||
1476                      (cond.isNOT_EQUAL() && c2 == 1)) {
1477                    // Fold away redundancy boolean_cmp
1478                    return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), cond2.flipCode(), prof);
1479                  }
1480                } else if (def.operator == BOOLEAN_CMP_ADDR) {
1481                  Address c1 = getAddressValue(BooleanCmp.getVal2(def));
1482                  ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
1483                  // x = a cmp c1 ? true : false; y = x cmp c2 ? true : false
1484                  if ((cond.isEQUAL() && c2 == 1)||
1485                      (cond.isNOT_EQUAL() && c2 == 0)) {
1486                    // Fold away redundancy boolean_cmp
1487                    return BooleanCmp.create(BOOLEAN_CMP_ADDR, y.copyRO(), a.copyRO(), AC(c1), cond2, prof);
1488                  } else if ((cond.isEQUAL() && c2 == 0)||
1489                      (cond.isNOT_EQUAL() && c2 == 1)) {
1490                    // Fold away redundancy boolean_cmp
1491                    return BooleanCmp.create(BOOLEAN_CMP_ADDR, y.copyRO(), a.copyRO(), AC(c1), cond2.flipCode(), prof);
1492                  }
1493                } else if (def.operator == BOOLEAN_CMP_FLOAT) {
1494                  float c1 = getFloatValue(BooleanCmp.getVal2(def));
1495                  ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
1496                  // x = a cmp c1 ? true : false; y = x cmp c2 ? true : false
1497                  if ((cond.isEQUAL() && c2 == 1)||
1498                      (cond.isNOT_EQUAL() && c2 == 0)) {
1499                    // Fold away redundancy boolean_cmp
1500                    return BooleanCmp.create(BOOLEAN_CMP_FLOAT, y.copyRO(), a.copyRO(), FC(c1), cond2, prof);
1501                  } else if ((cond.isEQUAL() && c2 == 0)||
1502                      (cond.isNOT_EQUAL() && c2 == 1)) {
1503                    // Fold away redundancy boolean_cmp
1504                    return BooleanCmp.create(BOOLEAN_CMP_FLOAT, y.copyRO(), a.copyRO(), FC(c1), cond2.flipCode(), prof);
1505                  }
1506                } else if (def.operator == BOOLEAN_CMP_DOUBLE) {
1507                  double c1 = getDoubleValue(BooleanCmp.getVal2(def));
1508                  ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
1509                  // x = a cmp c1 ? true : false; y = x cmp c2 ? true : false
1510                  if ((cond.isEQUAL() && c2 == 1)||
1511                      (cond.isNOT_EQUAL() && c2 == 0)) {
1512                    // Fold away redundancy boolean_cmp
1513                    return BooleanCmp.create(BOOLEAN_CMP_DOUBLE, y.copyRO(), a.copyRO(), DC(c1), cond2, prof);
1514                  } else if ((cond.isEQUAL() && c2 == 0)||
1515                      (cond.isNOT_EQUAL() && c2 == 1)) {
1516                    // Fold away redundancy boolean_cmp
1517                    return BooleanCmp.create(BOOLEAN_CMP_DOUBLE, y.copyRO(), a.copyRO(), DC(c1), cond2.flipCode(), prof);
1518                  }
1519                } else if (def.operator == LONG_CMP) {
1520                  long c1 = getLongValue(Binary.getVal2(def));
1521                  // x = a lcmp c1; y = y = x cmp c2 ? true : false
1522                  if (cond.isEQUAL() && c2 == 0) {
1523                    return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1),
1524                        ConditionOperand.EQUAL(), prof);
1525                  } else if (cond.isNOT_EQUAL() && c2 == 0) {
1526                    return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1),
1527                        ConditionOperand.NOT_EQUAL(), prof);
1528                  } else if ((cond.isEQUAL() && c2 == 1)||(cond.isGREATER() && c2 == 0)){
1529                    return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1),
1530                        ConditionOperand.GREATER(), prof);
1531                  } else if (cond.isGREATER_EQUAL() && c2 == 0){
1532                    return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1),
1533                        ConditionOperand.GREATER_EQUAL(), prof);
1534                  } else if ((cond.isEQUAL() && c2 == -1)||(cond.isLESS() && c2 == 0)) {
1535                    return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1),
1536                        ConditionOperand.LESS(), prof);
1537                  } else if (cond.isLESS_EQUAL() && c2 == 0) {
1538                    return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1),
1539                        ConditionOperand.LESS_EQUAL(), prof);
1540                  }
1541                }
1542              }
1543            }
1544            return null;
1545          }
1546          case BOOLEAN_CMP_LONG_opcode: {
1547            if (FOLD_LONGS && FOLD_CMPS) {
1548              long c2 = getLongValue(BooleanCmp.getVal2(s));
1549              ConditionOperand cond = (ConditionOperand) BooleanCmp.getCond(s).copy();
1550              BranchProfileOperand prof = (BranchProfileOperand) BooleanCmp.getBranchProfile(s).copy();
1551              if (cond.isEQUAL() || cond.isNOT_EQUAL()) {
1552                if (def.operator == LONG_ADD) {
1553                  long c1 = getLongValue(Binary.getVal2(def));
1554                  // x = a + c1; y = x cmp c2
1555                  return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c2 - c1), cond, prof);
1556                } else if (def.operator == LONG_SUB) {
1557                  long c1 = getLongValue(Binary.getVal2(def));
1558                  // x = a - c1; y = x cmp c2
1559                  return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1 + c2), cond, prof);
1560                } else if (def.operator == LONG_NEG) {
1561                  // x = -a; y = x cmp c2
1562                  return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), LC(-c2), cond.flipOperands(), prof);
1563                }
1564              }
1565            }
1566            return null;
1567          }
1568          case BOOLEAN_CMP_ADDR_opcode: {
1569            if (FOLD_REFS && FOLD_CMPS) {
1570              Address c2 = getAddressValue(BooleanCmp.getVal2(s));
1571              ConditionOperand cond = (ConditionOperand) BooleanCmp.getCond(s).copy();
1572              BranchProfileOperand prof = (BranchProfileOperand) BooleanCmp.getBranchProfile(s).copy();
1573              if (cond.isEQUAL() || cond.isNOT_EQUAL()) {
1574                if (def.operator == REF_ADD) {
1575                  Address c1 = getAddressValue(Binary.getVal2(def));
1576                  // x = a + c1; y = x cmp c2
1577                  return BooleanCmp.create(BOOLEAN_CMP_ADDR,
1578                      y.copyRO(),
1579                      a.copyRO(),
1580                      AC(c2.toWord().minus(c1.toWord()).toAddress()),
1581                      cond,
1582                      prof);
1583                } else if (def.operator == REF_SUB) {
1584                  Address c1 = getAddressValue(Binary.getVal2(def));
1585                  // x = a - c1; y = x cmp c2
1586                  return BooleanCmp.create(BOOLEAN_CMP_ADDR,
1587                      y.copyRO(),
1588                      a.copyRO(),
1589                      AC(c1.toWord().plus(c2.toWord()).toAddress()),
1590                      cond,
1591                      prof);
1592                } else if (def.operator == REF_NEG) {
1593                  // x = -a; y = x cmp c2
1594                  return BooleanCmp.create(BOOLEAN_CMP_ADDR,
1595                                           y.copyRO(),
1596                                           a.copyRO(),
1597                                           AC(Word.zero().minus(c2.toWord()).toAddress()),
1598                                           cond.flipOperands(),
1599                                           prof);
1600                }
1601              }
1602            }
1603            return null;
1604          }
1605          case INT_IFCMP_opcode: {
1606            if (FOLD_INTS && FOLD_IFCMPS) {
1607              int c2 = getIntValue(IfCmp.getVal2(s));
1608              ConditionOperand cond = (ConditionOperand) IfCmp.getCond(s).copy();
1609              BranchOperand target = (BranchOperand) IfCmp.getTarget(s).copy();
1610              BranchProfileOperand prof = (BranchProfileOperand) IfCmp.getBranchProfile(s).copy();
1611              if (cond.isEQUAL() || cond.isNOT_EQUAL()) {
1612                if (def.operator == INT_ADD) {
1613                  int c1 = getIntValue(Binary.getVal2(def));
1614                  // x = a + c1; y = x cmp c2
1615                  return IfCmp.create(INT_IFCMP, y.copyRO(), a.copyRO(), IC(c2 - c1), cond, target, prof);
1616                } else if (def.operator == INT_SUB) {
1617                  int c1 = getIntValue(Binary.getVal2(def));
1618                  // x = a - c1; y = x cmp c2
1619                  return IfCmp.create(INT_IFCMP, y.copyRO(), a.copyRO(), IC(c1 + c2), cond, target, prof);
1620                } else if (def.operator == INT_NEG) {
1621                    // x = -a; y = x cmp c2
1622                    return IfCmp.create(INT_IFCMP, y.copyRO(), a.copyRO(), IC(-c2), cond.flipOperands(), target, prof);
1623                } else if (def.operator == BOOLEAN_CMP_INT) {
1624                  int c1 = getIntValue(BooleanCmp.getVal2(def));
1625                  ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
1626                  // x = a cmp<cond2> c1 ? true : false; y = x cmp<cond> c2
1627                  if ((cond.isEQUAL() && c2 == 1)||
1628                      (cond.isNOT_EQUAL() && c2 == 0)) {
1629                    // Fold away redundant boolean_cmp
1630                    // x = a cmp<cond2> c1; y = x == 1  ==> y = a cmp<cond2> c1
1631                    return IfCmp.create(INT_IFCMP, y.copyRO(), a.copyRO(), IC(c1), cond2, target, prof);
1632                  } else if ((cond.isEQUAL() && c2 == 0)||
1633                      (cond.isNOT_EQUAL() && c2 == 1)) {
1634                    // Fold away redundant boolean_cmp
1635                    // x = a cmp<cond2> c1; y = x == 0  ==> y = a cmp<!cond2> c1
1636                    return IfCmp.create(INT_IFCMP, y.copyRO(), a.copyRO(), IC(c1), cond2.flipCode(), target, prof);
1637                  }
1638                } else if (def.operator == BOOLEAN_CMP_LONG) {
1639                  long c1 = getLongValue(BooleanCmp.getVal2(def));
1640                  ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
1641                  // x = a cmp c1 ? true : false; y = x cmp c2
1642                  if ((cond.isEQUAL() && c2 == 1)||
1643                      (cond.isNOT_EQUAL() && c2 == 0)) {
1644                    // Fold away redundant boolean_cmp
1645                    return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), cond2, target, prof);
1646                  } else if ((cond.isEQUAL() && c2 == 0)||
1647                      (cond.isNOT_EQUAL() && c2 == 1)) {
1648                    // Fold away redundant boolean_cmp
1649                    return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), cond2.flipCode(), target, prof);
1650                  }
1651                } else if (def.operator == BOOLEAN_CMP_ADDR) {
1652                  Address c1 = getAddressValue(BooleanCmp.getVal2(def));
1653                  ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
1654                  // x = a cmp c1 ? true : false; y = x cmp c2
1655                  if ((cond.isEQUAL() && c2 == 1)||
1656                    (cond.isNOT_EQUAL() && c2 == 0)) {
1657                    // Fold away redundant boolean_cmp
1658                    return IfCmp.create(REF_IFCMP, y.copyRO(), a.copyRO(), AC(c1), cond2, target, prof);
1659                  } else if ((cond.isEQUAL() && c2 == 0)||
1660                    (cond.isNOT_EQUAL() && c2 == 1)) {
1661                    // Fold away redundant boolean_cmp
1662                    return IfCmp.create(REF_IFCMP, y.copyRO(), a.copyRO(), AC(c1), cond2.flipCode(), target, prof);
1663                  }
1664                } else if (def.operator == BOOLEAN_CMP_FLOAT) {
1665                  float c1 = getFloatValue(BooleanCmp.getVal2(def));
1666                  ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
1667                  // x = a cmp c1 ? true : false; y = x cmp c2
1668                  if ((cond.isEQUAL() && c2 == 1)||
1669                      (cond.isNOT_EQUAL() && c2 == 0)) {
1670                    // Fold away redundant boolean_cmp
1671                    return IfCmp.create(FLOAT_IFCMP, y.copyRO(), a.copyRO(), FC(c1), cond2, target, prof);
1672                  } else if ((cond.isEQUAL() && c2 == 0)||
1673                      (cond.isNOT_EQUAL() && c2 == 1)) {
1674                    // Fold away redundant boolean_cmp
1675                    return IfCmp.create(FLOAT_IFCMP, y.copyRO(), a.copyRO(), FC(c1), cond2.flipCode(), target, prof);
1676                  }
1677                } else if (def.operator == BOOLEAN_CMP_DOUBLE) {
1678                  double c1 = getDoubleValue(BooleanCmp.getVal2(def));
1679                  ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
1680                  // x = a cmp c1 ? true : false; y = x cmp c2
1681                  if ((cond.isEQUAL() && c2 == 1)||
1682                      (cond.isNOT_EQUAL() && c2 == 0)) {
1683                    // Fold away redundant boolean_cmp
1684                    return IfCmp.create(DOUBLE_IFCMP, y.copyRO(), a.copyRO(), DC(c1), cond2, target, prof);
1685                  } else if ((cond.isEQUAL() && c2 == 0)||
1686                      (cond.isNOT_EQUAL() && c2 == 1)) {
1687                    // Fold away redundant boolean_cmp
1688                    return IfCmp.create(DOUBLE_IFCMP, y.copyRO(), a.copyRO(), DC(c1), cond2.flipCode(), target, prof);
1689                  }
1690                } else if (def.operator == LONG_CMP) {
1691                  long c1 = getLongValue(Binary.getVal2(def));
1692                  // x = a lcmp c1; y = y = x cmp c2
1693                  if (cond.isEQUAL() && c2 == 0) {
1694                    return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1),
1695                        ConditionOperand.EQUAL(), target, prof);
1696                  } else if (cond.isNOT_EQUAL() && c2 == 0) {
1697                    return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1),
1698                        ConditionOperand.NOT_EQUAL(), target, prof);
1699                  } else if ((cond.isEQUAL() && c2 == 1)||(cond.isGREATER() && c2 == 0)){
1700                    return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1),
1701                        ConditionOperand.GREATER(), target, prof);
1702                  } else if (cond.isGREATER_EQUAL() && c2 == 0){
1703                    return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1),
1704                        ConditionOperand.GREATER_EQUAL(), target, prof);
1705                  } else if ((cond.isEQUAL() && c2 == -1)||(cond.isLESS() && c2 == 0)) {
1706                    return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1),
1707                        ConditionOperand.LESS(), target, prof);
1708                  } else if (cond.isLESS_EQUAL() && c2 == 0) {
1709                    return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1),
1710                        ConditionOperand.LESS_EQUAL(), target, prof);
1711                  }
1712                }
1713              }
1714            }
1715            return null;
1716          }
1717          case LONG_IFCMP_opcode: {
1718            if (FOLD_LONGS && FOLD_IFCMPS) {
1719              long c2 = getLongValue(IfCmp.getVal2(s));
1720              ConditionOperand cond = (ConditionOperand) IfCmp.getCond(s).copy();
1721              BranchOperand target = (BranchOperand) IfCmp.getTarget(s).copy();
1722              BranchProfileOperand prof = (BranchProfileOperand) IfCmp.getBranchProfile(s).copy();
1723              if (cond.isEQUAL() || cond.isNOT_EQUAL()) {
1724                if (def.operator == LONG_ADD) {
1725                  long c1 = getLongValue(Binary.getVal2(def));
1726                  // x = a + c1; y = x cmp c2
1727                  return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c2 - c1), cond, target, prof);
1728                } else if (def.operator == LONG_SUB) {
1729                  long c1 = getLongValue(Binary.getVal2(def));
1730                  // x = a - c1; y = x cmp c2
1731                  return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1 + c2), cond, target, prof);
1732                } else if (def.operator == LONG_NEG) {
1733                  // x = -a; y = x cmp c2
1734                  return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(-c2), cond.flipOperands(), target, prof);
1735                }
1736              }
1737            }
1738            return null;
1739          }
1740          case FLOAT_IFCMP_opcode: {
1741            if (FOLD_FLOATS && FOLD_IFCMPS) {
1742              float c2 = getFloatValue(IfCmp.getVal2(s));
1743              ConditionOperand cond = (ConditionOperand) IfCmp.getCond(s).copy();
1744              BranchOperand target = (BranchOperand) IfCmp.getTarget(s).copy();
1745              BranchProfileOperand prof = (BranchProfileOperand) IfCmp.getBranchProfile(s).copy();
1746              if (def.operator == FLOAT_ADD) {
1747                float c1 = getFloatValue(Binary.getVal2(def));
1748                // x = a + c1; y = x cmp c2
1749                return IfCmp.create(FLOAT_IFCMP, y.copyRO(), a.copyRO(), FC(c2 - c1), cond, target, prof);
1750              } else if (def.operator == FLOAT_SUB) {
1751                float c1 = getFloatValue(Binary.getVal2(def));
1752                // x = a - c1; y = x cmp c2
1753                return IfCmp.create(FLOAT_IFCMP, y.copyRO(), a.copyRO(), FC(c1 + c2), cond, target, prof);
1754              } else if (def.operator == FLOAT_NEG) {
1755                // x = -a; y = x cmp c2
1756                return IfCmp.create(FLOAT_IFCMP, y.copyRO(), a.copyRO(), FC(-c2), cond.flipOperands(), target, prof);
1757              }
1758            }
1759            return null;
1760          }
1761          case DOUBLE_IFCMP_opcode: {
1762            if (FOLD_DOUBLES && FOLD_IFCMPS) {
1763              double c2 = getDoubleValue(IfCmp.getVal2(s));
1764              ConditionOperand cond = (ConditionOperand) IfCmp.getCond(s).copy();
1765              BranchOperand target = (BranchOperand) IfCmp.getTarget(s).copy();
1766              BranchProfileOperand prof = (BranchProfileOperand) IfCmp.getBranchProfile(s).copy();
1767              if (def.operator == DOUBLE_ADD) {
1768                double c1 = getDoubleValue(Binary.getVal2(def));
1769                // x = a + c1; y = x cmp c2
1770                return IfCmp.create(DOUBLE_IFCMP, y.copyRO(), a.copyRO(), DC(c2 - c1), cond, target, prof);
1771              } else if (def.operator == DOUBLE_SUB) {
1772                double c1 = getDoubleValue(Binary.getVal2(def));
1773                // x = a - c1; y = x cmp c2
1774                return IfCmp.create(DOUBLE_IFCMP, y.copyRO(), a.copyRO(), DC(c1 + c2), cond, target, prof);
1775              } else if (def.operator == DOUBLE_NEG) {
1776                // x = -a; y = x cmp c2
1777                return IfCmp.create(DOUBLE_IFCMP, y.copyRO(), a.copyRO(), DC(-c2), cond.flipOperands(), target, prof);
1778              }
1779            }
1780            return null;
1781          }
1782          case REF_IFCMP_opcode: {
1783            if (FOLD_REFS && FOLD_IFCMPS) {
1784              Address c2 = getAddressValue(IfCmp.getVal2(s));
1785              ConditionOperand cond = (ConditionOperand) IfCmp.getCond(s).copy();
1786              BranchOperand target = (BranchOperand) IfCmp.getTarget(s).copy();
1787              BranchProfileOperand prof = (BranchProfileOperand) IfCmp.getBranchProfile(s).copy();
1788              if (cond.isEQUAL() || cond.isNOT_EQUAL()) {
1789                if ((def.operator == NEW || def.operator == NEWARRAY) && c2.EQ(Address.zero())) {
1790                  // x = new ... ; y = x cmp null
1791                  return IfCmp.create(REF_IFCMP,
1792                      y.copyRO(),
1793                      AC(Address.zero()),
1794                      AC(Address.zero()),
1795                      cond.flipCode(),
1796                      target,
1797                      prof);
1798                } else if (def.operator == REF_ADD) {
1799                  Address c1 = getAddressValue(Binary.getVal2(def));
1800                  // x = a + c1; y = x cmp c2
1801                  return IfCmp.create(REF_IFCMP,
1802                                      y.copyRO(),
1803                                      a.copyRO(),
1804                                      AC(c2.toWord().minus(c1.toWord()).toAddress()),
1805                                      cond,
1806                                      target,
1807                                      prof);
1808                } else if (def.operator == REF_SUB) {
1809                  Address c1 = getAddressValue(Binary.getVal2(def));
1810                  // x = a - c1; y = x cmp c2
1811                  return IfCmp.create(REF_IFCMP,
1812                                      y.copyRO(),
1813                                      a.copyRO(),
1814                                      AC(c1.toWord().plus(c2.toWord()).toAddress()),
1815                                      cond,
1816                                      target,
1817                                      prof);
1818                } else if (def.operator == REF_NEG) {
1819                  // x = -a; y = x cmp c2
1820                  return IfCmp.create(REF_IFCMP,
1821                                      y.copyRO(),
1822                                      a.copyRO(),
1823                                      AC(Word.zero().minus(c2.toWord()).toAddress()),
1824                                      cond.flipOperands(),
1825                                      target,
1826                                      prof);
1827                }
1828              }
1829            }
1830            return null;
1831          }
1832          case INT_IFCMP2_opcode: {
1833            if (FOLD_INTS && FOLD_IFCMPS) {
1834              int c2 = getIntValue(IfCmp2.getVal2(s));
1835              ConditionOperand cond1 = (ConditionOperand) IfCmp2.getCond1(s).copy();
1836              ConditionOperand cond2 = (ConditionOperand) IfCmp2.getCond2(s).copy();
1837              BranchOperand target1 = (BranchOperand) IfCmp2.getTarget1(s).copy();
1838              BranchOperand target2 = (BranchOperand) IfCmp2.getTarget2(s).copy();
1839              BranchProfileOperand prof1 = (BranchProfileOperand) IfCmp2.getBranchProfile1(s).copy();
1840              BranchProfileOperand prof2 = (BranchProfileOperand) IfCmp2.getBranchProfile2(s).copy();
1841              if ((cond1.isEQUAL() || cond1.isNOT_EQUAL())&&(cond2.isEQUAL() || cond2.isNOT_EQUAL())) {
1842                if (def.operator == INT_ADD) {
1843                  int c1 = getIntValue(Binary.getVal2(def));
1844                  // x = a + c1; y = x cmp c2
1845                  return IfCmp2.create(INT_IFCMP2,
1846                                       y.copyRO(),
1847                                       a.copyRO(),
1848                                       IC(c2 - c1),
1849                                       cond1,
1850                                       target1,
1851                                       prof1,
1852                                       cond2,
1853                                       target2,
1854                                       prof2);
1855                } else if (def.operator == INT_SUB) {
1856                  int c1 = getIntValue(Binary.getVal2(def));
1857                  // x = a - c1; y = x cmp c2
1858                  return IfCmp2.create(INT_IFCMP2,
1859                                       y.copyRO(),
1860                                       a.copyRO(),
1861                                       IC(c1 + c2),
1862                                       cond1,
1863                                       target1,
1864                                       prof1,
1865                                       cond2,
1866                                       target2,
1867                                       prof2);
1868                } else if (def.operator == INT_NEG) {
1869                  // x = -a; y = x cmp c2
1870                  return IfCmp2.create(INT_IFCMP2,
1871                                       y.copyRO(),
1872                                       a.copyRO(),
1873                                       IC(-c2),
1874                                       cond1.flipOperands(),
1875                                       target1,
1876                                       prof1,
1877                                       cond2.flipOperands(),
1878                                       target2,
1879                                       prof2);
1880                }
1881              }
1882            }
1883            return null;
1884          }
1885    
1886          case INT_COND_MOVE_opcode:
1887          case LONG_COND_MOVE_opcode:
1888          case REF_COND_MOVE_opcode:
1889          case FLOAT_COND_MOVE_opcode:
1890          case DOUBLE_COND_MOVE_opcode:
1891          case GUARD_COND_MOVE_opcode: {
1892            if (FOLD_INTS && FOLD_CONDMOVES) {
1893              Operand trueValue = CondMove.getTrueValue(s);
1894              Operand falseValue = CondMove.getFalseValue(s);
1895              ConditionOperand cond = (ConditionOperand) CondMove.getCond(s).copy();
1896              boolean isEqualityTest = cond.isEQUAL() || cond.isNOT_EQUAL();
1897              switch (def.operator.opcode) {
1898                case INT_ADD_opcode:
1899                  if (isEqualityTest) {
1900                    int c1 = getIntValue(Binary.getVal2(def));
1901                    int c2 = getIntValue(CondMove.getVal2(s));
1902                    // x = a + c1; y = x cmp c2 ? trueValue : falseValue
1903                    return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), IC(c2 - c1), cond, trueValue, falseValue);
1904                  }
1905                  break;
1906                case LONG_ADD_opcode:
1907                  if (isEqualityTest) {
1908                    long c1 = getLongValue(Binary.getVal2(def));
1909                    long c2 = getLongValue(CondMove.getVal2(s));
1910                    // x = a + c1; y = x cmp c2 ? trueValue : falseValue
1911                    return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c2 - c1), cond, trueValue, falseValue);
1912                  }
1913                  break;
1914                case REF_ADD_opcode:
1915                  if (isEqualityTest) {
1916                    Address c1 = getAddressValue(Binary.getVal2(def));
1917                    Address c2 = getAddressValue(CondMove.getVal2(s));
1918                    // x = a + c1; y = x cmp c2 ? trueValue : falseValue
1919                    return CondMove.create(s.operator(),
1920                        y.copyRO(),
1921                        a.copyRO(),
1922                        AC(c2.toWord().minus(c1.toWord()).toAddress()),
1923                        cond,
1924                        trueValue,
1925                        falseValue);
1926                  }
1927                  break;
1928                case FLOAT_ADD_opcode: {
1929                  float c1 = getFloatValue(Binary.getVal2(def));
1930                  float c2 = getFloatValue(CondMove.getVal2(s));
1931                  // x = a + c1; y = x cmp c2 ? trueValue : falseValue
1932                  return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), FC(c2 - c1), cond, trueValue, falseValue);
1933                }
1934                case DOUBLE_ADD_opcode: {
1935                  double c1 = getDoubleValue(Binary.getVal2(def));
1936                  double c2 = getDoubleValue(CondMove.getVal2(s));
1937                  // x = a + c1; y = x cmp c2 ? trueValue : falseValue
1938                  return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), DC(c2 - c1), cond, trueValue, falseValue);
1939                }
1940                case INT_SUB_opcode:
1941                  if (isEqualityTest) {
1942                    int c1 = getIntValue(Binary.getVal2(def));
1943                    int c2 = getIntValue(CondMove.getVal2(s));
1944                    // x = a - c1; y = x cmp c2 ? trueValue : falseValue
1945                    return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), IC(c1 + c2), cond, trueValue, falseValue);
1946                  }
1947                  break;
1948                case LONG_SUB_opcode:
1949                  if (isEqualityTest) {
1950    
1951                    long c1 = getLongValue(Binary.getVal2(def));
1952                    long c2 = getLongValue(CondMove.getVal2(s));
1953                    // x = a - c1; y = x cmp c2 ? trueValue : falseValue
1954                    return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c1 + c2), cond, trueValue, falseValue);
1955                  }
1956                  break;
1957                case REF_SUB_opcode:
1958                  if (isEqualityTest) {
1959                    Address c1 = getAddressValue(Binary.getVal2(def));
1960                    Address c2 = getAddressValue(CondMove.getVal2(s));
1961                    // x = a - c1; y = x cmp c2 ? trueValue : falseValue
1962                    return CondMove.create(s.operator(),
1963                        y.copyRO(),
1964                        a.copyRO(),
1965                        AC(c1.toWord().plus(c2.toWord()).toAddress()),
1966                        cond,
1967                        trueValue,
1968                        falseValue);
1969                  }
1970                  break;
1971                case FLOAT_SUB_opcode: {
1972                  float c1 = getFloatValue(Binary.getVal2(def));
1973                  float c2 = getFloatValue(CondMove.getVal2(s));
1974                  // x = a - c1; y = x cmp c2 ? trueValue : falseValue
1975                  return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), FC(c1 + c2), cond, trueValue, falseValue);
1976                }
1977                case DOUBLE_SUB_opcode: {
1978                  double c1 = getDoubleValue(Binary.getVal2(def));
1979                  double c2 = getDoubleValue(CondMove.getVal2(s));
1980                  // x = a - c1; y = x cmp c2 ? trueValue : falseValue
1981                  return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), DC(c1 + c2), cond, trueValue, falseValue);
1982                }
1983                case INT_NEG_opcode:
1984                  if (isEqualityTest) {
1985                    int c2 = getIntValue(CondMove.getVal2(s));
1986                    // x = -a; y = x cmp c2 ? trueValue : falseValue
1987                    return CondMove.create(s.operator(),
1988                        y.copyRO(),
1989                        a.copyRO(),
1990                        IC(-c2),
1991                        cond.flipOperands(),
1992                        trueValue,
1993                        falseValue);
1994                  }
1995                  break;
1996                case LONG_NEG_opcode:
1997                  if (isEqualityTest) {
1998                    long c2 = getLongValue(CondMove.getVal2(s));
1999                    // x = -a; y = x cmp c2 ? trueValue : falseValue
2000                    return CondMove.create(s.operator(),
2001                        y.copyRO(),
2002                        a.copyRO(),
2003                        LC(-c2),
2004                        cond.flipOperands(),
2005                        trueValue,
2006                        falseValue);
2007                  }
2008                  break;
2009                case REF_NEG_opcode:
2010                  if (isEqualityTest) {
2011                    Address c2 = getAddressValue(CondMove.getVal2(s));
2012                    // x = -a; y = x cmp c2 ? trueValue : falseValue
2013                    return CondMove.create(s.operator(),
2014                        y.copyRO(),
2015                        a.copyRO(),
2016                        AC(Word.zero().minus(c2.toWord()).toAddress()),
2017                        cond.flipOperands(),
2018                        trueValue,
2019                        falseValue);
2020                  }
2021                  break;
2022                case FLOAT_NEG_opcode: {
2023                  float c2 = getFloatValue(CondMove.getVal2(s));
2024                  // x = -a; y = x cmp c2 ? trueValue : falseValue
2025                  return CondMove.create(s.operator(),
2026                                         y.copyRO(),
2027                                         a.copyRO(),
2028                                         FC(-c2),
2029                                         cond.flipOperands(),
2030                                         trueValue,
2031                                         falseValue);
2032                }
2033                case DOUBLE_NEG_opcode: {
2034                  double c2 = getDoubleValue(CondMove.getVal2(s));
2035                  // x = -a; y = x cmp c2 ? trueValue : falseValue
2036                  return CondMove.create(s.operator(),
2037                                         y.copyRO(),
2038                                         a.copyRO(),
2039                                         DC(-c2),
2040                                         cond.flipOperands(),
2041                                         trueValue,
2042                                         falseValue);
2043                }
2044                case BOOLEAN_CMP_INT_opcode: {
2045                  int c1 = getIntValue(BooleanCmp.getVal2(def));
2046                  int c2 = getIntValue(CondMove.getVal2(s));
2047                  // x = a cmp c1 ? true : false; y = x cmp c2 ? trueValue : falseValue
2048                  if ((cond.isEQUAL() && c2 == 1)||
2049                      (cond.isNOT_EQUAL() && c2 == 0)) {
2050                    return CondMove.create(s.operator(),
2051                        y.copyRO(),
2052                        a.copyRO(),
2053                        IC(c1),
2054                        BooleanCmp.getCond(def).copy().asCondition(),
2055                        trueValue,
2056                        falseValue);
2057                  } else if ((cond.isEQUAL() && c2 == 0)||
2058                      (cond.isNOT_EQUAL() && c2 == 1)) {
2059                    return CondMove.create(s.operator(),
2060                        y.copyRO(),
2061                        a.copyRO(),
2062                        IC(c1),
2063                        BooleanCmp.getCond(def).copy().asCondition().flipCode(),
2064                        trueValue,
2065                        falseValue);
2066                  }
2067                  break;
2068                }
2069                case BOOLEAN_CMP_ADDR_opcode: {
2070                  Address c1 = getAddressValue(BooleanCmp.getVal2(def));
2071                  int c2 = getIntValue(CondMove.getVal2(s));
2072                  // x = a cmp c1 ? true : false; y = x cmp c2 ? trueValue : falseValue
2073                  if ((cond.isEQUAL() && c2 == 1)||
2074                      (cond.isNOT_EQUAL() && c2 == 0)) {
2075                    return CondMove.create(s.operator(),
2076                        y.copyRO(),
2077                        a.copyRO(),
2078                        AC(c1),
2079                        BooleanCmp.getCond(def).copy().asCondition(),
2080                        trueValue,
2081                        falseValue);
2082                  } else if ((cond.isEQUAL() && c2 == 0)||
2083                      (cond.isNOT_EQUAL() && c2 == 1)) {
2084                    return CondMove.create(s.operator(),
2085                        y.copyRO(),
2086                        a.copyRO(),
2087                        AC(c1),
2088                        BooleanCmp.getCond(def).flipCode(),
2089                        trueValue,
2090                        falseValue);
2091                  }
2092                  break;
2093                }
2094                case BOOLEAN_CMP_LONG_opcode: {
2095                  long c1 = getLongValue(BooleanCmp.getVal2(def));
2096                  int c2 = getIntValue(CondMove.getVal2(s));
2097                  // x = a cmp c1 ? true : false; y = x cmp c2 ? trueValue : falseValue
2098                  if ((cond.isEQUAL() && c2 == 1)||
2099                      (cond.isNOT_EQUAL() && c2 == 0)) {
2100                    return CondMove.create(s.operator(),
2101                        y.copyRO(),
2102                        a.copyRO(),
2103                        LC(c1),
2104                        BooleanCmp.getCond(def).copy().asCondition(),
2105                        trueValue,
2106                        falseValue);
2107                  } else if ((cond.isEQUAL() && c2 == 0)||
2108                      (cond.isNOT_EQUAL() && c2 == 1)) {
2109                    return CondMove.create(s.operator(),
2110                        y.copyRO(),
2111                        a.copyRO(),
2112                        LC(c1),
2113                        BooleanCmp.getCond(def).copy().asCondition().flipCode(),
2114                        trueValue,
2115                        falseValue);
2116                  } else {
2117                    return null;
2118                  }
2119                }
2120                case BOOLEAN_CMP_DOUBLE_opcode: {
2121                  double c1 = getDoubleValue(BooleanCmp.getVal2(def));
2122                  int c2 = getIntValue(CondMove.getVal2(s));
2123                  // x = a cmp c1 ? true : false; y = x cmp c2 ? trueValue : falseValue
2124                  if ((cond.isEQUAL() && c2 == 1)||
2125                      (cond.isNOT_EQUAL() && c2 == 0)) {
2126                    return CondMove.create(s.operator(),
2127                        y.copyRO(),
2128                        a.copyRO(),
2129                        DC(c1),
2130                        BooleanCmp.getCond(def).copy().asCondition(),
2131                        trueValue,
2132                        falseValue);
2133                  } else if ((cond.isEQUAL() && c2 == 0)||
2134                      (cond.isNOT_EQUAL() && c2 == 1)) {
2135                    return CondMove.create(s.operator(),
2136                        y.copyRO(),
2137                        a.copyRO(),
2138                        DC(c1),
2139                        BooleanCmp.getCond(def).copy().asCondition().flipCode(),
2140                        trueValue,
2141                        falseValue);
2142                  }
2143                  break;
2144                }
2145                case BOOLEAN_CMP_FLOAT_opcode: {
2146                  float c1 = getFloatValue(BooleanCmp.getVal2(def));
2147                  int c2 = getIntValue(CondMove.getVal2(s));
2148                  // x = a cmp c1 ? true : false; y = x cmp c2 ? trueValue : falseValue
2149                  if ((cond.isEQUAL() && c2 == 1)||
2150                      (cond.isNOT_EQUAL() && c2 == 0)) {
2151                    return CondMove.create(s.operator(),
2152                        y.copyRO(),
2153                        a.copyRO(),
2154                        FC(c1),
2155                        BooleanCmp.getCond(def).copy().asCondition(),
2156                        trueValue,
2157                        falseValue);
2158                  } else if ((cond.isEQUAL() && c2 == 0)||
2159                      (cond.isNOT_EQUAL() && c2 == 1)) {
2160                    return CondMove.create(s.operator(),
2161                        y.copyRO(),
2162                        a.copyRO(),
2163                        FC(c1),
2164                        BooleanCmp.getCond(def).copy().asCondition().flipCode(),
2165                        trueValue,
2166                        falseValue);
2167                  }
2168                  break;
2169                }
2170                case LONG_CMP_opcode: {
2171                  long c1 = getLongValue(Binary.getVal2(def));
2172                  int c2 = getIntValue(CondMove.getVal2(s));
2173                  // x = a lcmp c1; y = y = x cmp c2 ? trueValue : falseValue
2174                  if (cond.isEQUAL() && c2 == 0) {
2175                    return CondMove.create(s.operator(),
2176                        y.copyRO(),
2177                        a.copyRO(),
2178                        LC(c1),
2179                        ConditionOperand.EQUAL(),
2180                        trueValue,
2181                        falseValue);
2182                  } else if (cond.isNOT_EQUAL() && c2 == 0) {
2183                    return CondMove.create(s.operator(),
2184                        y.copyRO(),
2185                        a.copyRO(),
2186                        LC(c1),
2187                        ConditionOperand.NOT_EQUAL(),
2188                        trueValue,
2189                        falseValue);
2190                  } else if ((cond.isEQUAL() && c2 == 1)||(cond.isGREATER() && c2 == 0)){
2191                    return CondMove.create(s.operator(),
2192                        y.copyRO(),
2193                        a.copyRO(),
2194                        LC(c1),
2195                        ConditionOperand.GREATER(),
2196                        trueValue,
2197                        falseValue);
2198                  } else if (cond.isGREATER_EQUAL() && c2 == 0){
2199                    return CondMove.create(s.operator(),
2200                        y.copyRO(),
2201                        a.copyRO(),
2202                        LC(c1),
2203                        ConditionOperand.GREATER_EQUAL(),
2204                        trueValue,
2205                        falseValue);
2206                  } else if ((cond.isEQUAL() && c2 == -1)||(cond.isLESS() && c2 == 0)) {
2207                    return CondMove.create(s.operator(),
2208                        y.copyRO(),
2209                        a.copyRO(),
2210                        LC(c1),
2211                        ConditionOperand.LESS(),
2212                        trueValue,
2213                        falseValue);
2214                  } else if (cond.isLESS_EQUAL() && c2 == 0) {
2215                    return CondMove.create(s.operator(),
2216                        y.copyRO(),
2217                        a.copyRO(),
2218                        LC(c1),
2219                        ConditionOperand.LESS_EQUAL(),
2220                        trueValue,
2221                        falseValue);
2222                  }
2223                  break;
2224                }
2225                default:
2226              }
2227            }
2228            return null;
2229          }
2230    
2231          case INT_NEG_opcode: {
2232            if (FOLD_INTS && FOLD_NEGS) {
2233              if (def.operator == INT_NEG) {
2234                // x = -z; y = -x;
2235                return Move.create(INT_MOVE, y.copyRO(), Unary.getVal(def).copy());
2236              } else if (def.operator == INT_MUL) {
2237                int c1 = getIntValue(Binary.getVal2(def));
2238                // x = a * c1; y = -x;
2239                return Binary.create(INT_MUL, y.copyRO(), a.copyRO(), IC(-c1));
2240              } else if (def.operator == INT_DIV) {
2241                int c1 = getIntValue(GuardedBinary.getVal2(def));
2242                Operand guard = GuardedBinary.getGuard(def);
2243                // x = a / c1; y = -x;
2244                return GuardedBinary.create(INT_DIV, y.copyRO(), a.copyRO(), IC(-c1), guard.copy());
2245              } else if (FOLD_CONSTANTS_TO_LHS && (def.operator == INT_ADD)) {
2246                int c1 = getIntValue(Binary.getVal2(def));
2247                // x = a + c1; y = -x;
2248                return Binary.create(INT_SUB, y.copyRO(), IC(-c1), a.copyRO());
2249              } else if (FOLD_CONSTANTS_TO_LHS && (def.operator == INT_SUB)) {
2250                int c1 = getIntValue(Binary.getVal2(def));
2251                // x = a - c1; y = -x;
2252                return Binary.create(INT_SUB, y.copyRO(), IC(c1), a.copyRO());
2253              }
2254            }
2255            return null;
2256          }
2257    
2258          case REF_NEG_opcode: {
2259            if (FOLD_REFS && FOLD_NEGS) {
2260              if (def.operator == REF_NEG) {
2261                // x = -z; y = -x;
2262                return Move.create(REF_MOVE, y.copyRO(), Unary.getVal(def).copy());
2263              } else if (FOLD_CONSTANTS_TO_LHS && (def.operator == REF_ADD)) {
2264                Address c1 = getAddressValue(Binary.getVal2(def));
2265                // x = a + c1; y = -x;
2266                return Binary.create(REF_SUB, y.copyRO(), AC(Word.zero().minus(c1.toWord()).toAddress()), a.copyRO());
2267              } else if (FOLD_CONSTANTS_TO_LHS && (def.operator == REF_SUB)) {
2268                Address c1 = getAddressValue(Binary.getVal2(def));
2269                // x = a - c1; y = -x;
2270                return Binary.create(REF_SUB, y.copyRO(), AC(c1), a.copyRO());
2271              }
2272            }
2273            return null;
2274          }
2275    
2276          case LONG_NEG_opcode: {
2277            if (FOLD_LONGS && FOLD_NEGS) {
2278              if (def.operator == LONG_NEG) {
2279                // x = -z; y = -x;
2280                return Move.create(LONG_MOVE, y.copyRO(), Unary.getVal(def).copy());
2281              } else if (def.operator == LONG_MUL) {
2282                long c1 = getLongValue(Binary.getVal2(def));
2283                // x = a * c1; y = -x;
2284                return Binary.create(LONG_MUL, y.copyRO(), a.copyRO(), LC(-c1));
2285              } else if (def.operator == LONG_DIV) {
2286                long c1 = getLongValue(GuardedBinary.getVal2(def));
2287                Operand guard = GuardedBinary.getGuard(def);
2288                // x = a / c1; y = -x;
2289                return GuardedBinary.create(LONG_DIV, y.copyRO(), a.copyRO(), LC(-c1), guard.copy());
2290              } else if (FOLD_CONSTANTS_TO_LHS && (def.operator == LONG_ADD)) {
2291                long c1 = getLongValue(Binary.getVal2(def));
2292                // x = a + c1; y = -x;
2293                return Binary.create(LONG_SUB, y.copyRO(), LC(-c1), a.copyRO());
2294              } else if (FOLD_CONSTANTS_TO_LHS && (def.operator == LONG_SUB)) {
2295                long c1 = getLongValue(Binary.getVal2(def));
2296                // x = a - c1; y = -x;
2297                return Binary.create(LONG_SUB, y.copyRO(), LC(c1), a.copyRO());
2298              }
2299            }
2300            return null;
2301          }
2302    
2303          case FLOAT_NEG_opcode: {
2304            if (FOLD_FLOATS && FOLD_NEGS) {
2305              if (def.operator == FLOAT_NEG) {
2306                // x = -z; y = -x;
2307                return Move.create(FLOAT_MOVE, y.copyRO(), Unary.getVal(def).copy());
2308              } else if (def.operator == FLOAT_MUL) {
2309                float c1 = getFloatValue(Binary.getVal2(def));
2310                // x = a * c1; y = -x;
2311                return Binary.create(FLOAT_MUL, y.copyRO(), a.copyRO(), FC(-c1));
2312              } else if (def.operator == FLOAT_DIV) {
2313                float c1 = getFloatValue(Binary.getVal2(def));
2314                // x = a / c1; y = -x;
2315                return Binary.create(FLOAT_DIV, y.copyRO(), a.copyRO(), FC(-c1));
2316              } else if (FOLD_CONSTANTS_TO_LHS && (def.operator == FLOAT_ADD)) {
2317                float c1 = getFloatValue(Binary.getVal2(def));
2318                // x = a + c1; y = -x;
2319                return Binary.create(FLOAT_SUB, y.copyRO(), FC(-c1), a.copyRO());
2320              } else if (FOLD_CONSTANTS_TO_LHS && (def.operator == FLOAT_SUB)) {
2321                float c1 = getFloatValue(Binary.getVal2(def));
2322                // x = a - c1; y = -x;
2323                return Binary.create(FLOAT_SUB, y.copyRO(), FC(c1), a.copyRO());
2324              }
2325            }
2326            return null;
2327          }
2328    
2329          case DOUBLE_NEG_opcode: {
2330            if (FOLD_DOUBLES && FOLD_NEGS) {
2331              if (def.operator == DOUBLE_NEG) {
2332                // x = -z; y = -x;
2333                return Move.create(DOUBLE_MOVE, y.copyRO(), Unary.getVal(def).copy());
2334              } else if (def.operator == DOUBLE_MUL) {
2335                double c1 = getDoubleValue(Binary.getVal2(def));
2336                // x = a * c1; y = -x;
2337                return Binary.create(DOUBLE_MUL, y.copyRO(), a.copyRO(), DC(-c1));
2338              } else if (def.operator == DOUBLE_DIV) {
2339                double c1 = getDoubleValue(Binary.getVal2(def));
2340                // x = a / c1; y = -x;
2341                return Binary.create(DOUBLE_DIV, y.copyRO(), a.copyRO(), DC(-c1));
2342              } else if (FOLD_CONSTANTS_TO_LHS && (def.operator == DOUBLE_ADD)) {
2343                double c1 = getDoubleValue(Binary.getVal2(def));
2344                // x = a + c1; y = -x;
2345                return Binary.create(DOUBLE_SUB, y.copyRO(), DC(-c1), a.copyRO());
2346              } else if (FOLD_CONSTANTS_TO_LHS && (def.operator == DOUBLE_SUB)) {
2347                double c1 = getDoubleValue(Binary.getVal2(def));
2348                // x = a - c1; y = -x;
2349                return Binary.create(DOUBLE_SUB, y.copyRO(), DC(c1), a.copyRO());
2350              }
2351            }
2352            return null;
2353          }
2354    
2355          case BOOLEAN_NOT_opcode: {
2356            if (FOLD_INTS && FOLD_NOTS) {
2357              if (def.operator == BOOLEAN_NOT) {
2358                // x = 1 ^ a; y = 1 ^ x;
2359                return Move.create(INT_MOVE, y.copyRO(), Unary.getVal(def).copy());
2360              } else if (BooleanCmp.conforms(def)) {
2361                // x = a cmp b; y = !x
2362                return BooleanCmp.create(def.operator,
2363                                         y.copyRO(),
2364                                         BooleanCmp.getVal1(def).copy(),
2365                                         BooleanCmp.getVal2(def).copy(),
2366                                         ((ConditionOperand) BooleanCmp.getCond(def).copy()).flipCode(),
2367                                         ((BranchProfileOperand) BooleanCmp.getBranchProfile(def).copy()));
2368              }
2369            }
2370            return null;
2371          }
2372    
2373          case INT_NOT_opcode: {
2374            if (FOLD_INTS && FOLD_NOTS) {
2375              if (def.operator == INT_NOT) {
2376                // x = -1 ^ a; y = -1 ^ x;
2377                return Move.create(INT_MOVE, y.copyRO(), a.copy());
2378              }
2379            }
2380            return null;
2381          }
2382    
2383          case REF_NOT_opcode: {
2384            if (FOLD_REFS && FOLD_NOTS) {
2385              if (def.operator == REF_NOT) {
2386                // x = -1 ^ a; y = -1 ^ x;
2387                return Move.create(REF_MOVE, y.copyRO(), a.copy());
2388              }
2389            }
2390            return null;
2391          }
2392    
2393          case LONG_NOT_opcode: {
2394            if (FOLD_LONGS && FOLD_NOTS) {
2395              if (def.operator == LONG_NOT) {
2396                // x = -1 ^ a; y = -1 ^ x;
2397                return Move.create(LONG_MOVE, y.copyRO(), a.copy());
2398              }
2399            }
2400            return null;
2401          }
2402    
2403          case INT_2BYTE_opcode: {
2404            if (FOLD_INTS && FOLD_2CONVERSION) {
2405              if ((def.operator == INT_2BYTE) || (def.operator == INT_2SHORT)) {
2406                // x = (short)a; y = (byte)x;
2407                return Unary.create(INT_2BYTE, y.copyRO(), a.copy());
2408              } else if (def.operator == INT_2USHORT) {
2409                // x = (char)a; y = (byte)x;
2410                return Binary.create(INT_AND, y.copyRO(), a.copy(), IC(0xFF));
2411              }
2412            }
2413            return null;
2414          }
2415          case INT_2SHORT_opcode: {
2416            if (FOLD_INTS && FOLD_2CONVERSION) {
2417              if (def.operator == INT_2BYTE) {
2418                // x = (byte)a; y = (short)x;
2419                return Unary.create(INT_2BYTE, y.copyRO(), a.copy());
2420              } else if (def.operator == INT_2SHORT) {
2421                // x = (short)a; y = (short)x;
2422                return Unary.create(INT_2SHORT, y.copyRO(), a.copy());
2423              } else if (def.operator == INT_2USHORT) {
2424                // x = (char)a; y = (short)x;
2425                return Unary.create(INT_2USHORT, y.copyRO(), a.copy());
2426              }
2427            }
2428            return null;
2429          }
2430          case INT_2USHORT_opcode: {
2431            if (FOLD_INTS && FOLD_2CONVERSION) {
2432              if ((def.operator == INT_2SHORT) || (def.operator == INT_2USHORT)) {
2433                // x = (short)a; y = (char)x;
2434                return Unary.create(INT_2USHORT, y.copyRO(), a.copy());
2435              }
2436            }
2437            return null;
2438          }
2439    
2440          case LONG_2INT_opcode: {
2441            if (FOLD_LONGS && FOLD_2CONVERSION) {
2442              if (def.operator == INT_2LONG) {
2443                // x = (long)a; y = (int)x;
2444                return Move.create(INT_MOVE, y.copyRO(), a.copy());
2445              }
2446            }
2447            return null;
2448          }
2449          case INT_2LONG_opcode:
2450            // unused
2451            return null;
2452    
2453          case DOUBLE_2FLOAT_opcode: {
2454            if (FOLD_DOUBLES && FOLD_2CONVERSION) {
2455              if (def.operator == FLOAT_2DOUBLE) {
2456                // x = (double)a; y = (float)x;
2457                return Move.create(FLOAT_MOVE, y.copyRO(), a.copy());
2458              }
2459            }
2460            return null;
2461          }
2462    
2463          case FLOAT_2DOUBLE_opcode:
2464            // unused
2465            return null;
2466          case INT_ZERO_CHECK_opcode: {
2467            if (FOLD_INTS && FOLD_CHECKS) {
2468              if (def.operator == INT_NEG) {
2469                // x = -z; y = zerocheck x;
2470                return ZeroCheck.create(INT_ZERO_CHECK, y.copyRO(), Unary.getVal(def).copy());
2471              }
2472            }
2473            return null;
2474          }
2475          case LONG_ZERO_CHECK_opcode: {
2476            if (FOLD_INTS && FOLD_CHECKS) {
2477              if (def.operator == INT_NEG) {
2478                // x = -z; y = zerocheck x;
2479                return ZeroCheck.create(INT_ZERO_CHECK, y.copyRO(), Unary.getVal(def).copy());
2480              }
2481            }
2482            return null;
2483          }
2484          case NEWARRAY_opcode:
2485            // unused
2486            return null;
2487          case BOUNDS_CHECK_opcode: {
2488            if (FOLD_CHECKS) {
2489              if (def.operator == NEWARRAY) {
2490                // x = newarray xxx[c1]; y = boundscheck x, c2;
2491                int c1 = getIntValue(NewArray.getSize(def));
2492                int c2 = getIntValue(BoundsCheck.getIndex(s));
2493                if (c2 >= 0 && c2 < c1) {
2494                  return Move.create(GUARD_MOVE, y.copyRO(), BoundsCheck.getGuard(def).copy());
2495                }
2496              }
2497            }
2498            return null;
2499          }
2500          case NULL_CHECK_opcode: {
2501            if (FOLD_CHECKS) {
2502              if (def.operator == NEWARRAY || def.operator == NEW) {
2503                // x = new xxx; y = nullcheck x;
2504                return Move.create(GUARD_MOVE, y.copyRO(), new TrueGuardOperand());
2505              }
2506            }
2507            return null;
2508          }
2509          case INSTANCEOF_opcode: {
2510            if (FOLD_CHECKS) {
2511              TypeReference newType;
2512              if (def.operator == NEW) {
2513                // x = new xxx; y = instanceof x, zzz;
2514                newType = New.getType(def).getTypeRef();
2515              } else if (def.operator == NEWARRAY) {
2516                // x = newarray xxx; y = instanceof x, zzz;
2517                newType = NewArray.getType(def).getTypeRef();
2518              } else {
2519                return null;
2520              }
2521              TypeReference instanceofType = InstanceOf.getType(s).getTypeRef();
2522              if (newType == instanceofType) {
2523                return Move.create(INT_MOVE, y.copyRO(), IC(1));
2524              } else {
2525                return Move.create(INT_MOVE, y.copyRO(), IC(RuntimeEntrypoints.isAssignableWith(instanceofType.resolve(), newType.resolve()) ? 1 : 0));
2526              }
2527            }
2528            return null;
2529          }
2530          case ARRAYLENGTH_opcode: {
2531            if (FOLD_CHECKS) {
2532              if (def.operator() == NEWARRAY) {
2533                // x = newarray xxx[c1]; y = arraylength x;
2534                return Move.create(INT_MOVE, y.copyRO(), NewArray.getSize(def).copy());
2535              }
2536            }
2537            return null;
2538          }
2539          default:
2540            OptimizingCompilerException.UNREACHABLE();
2541            return null;
2542        }
2543      }
2544    
2545      /**
2546       * Does instruction s compute a register r = candidate expression?
2547       *
2548       * @param s the instruction
2549       * @param ssa are we in SSA form?
2550       * @return the computed register, or {@code null}
2551       */
2552      private static Register isCandidateExpression(Instruction s, boolean ssa) {
2553    
2554        switch (s.operator.opcode) {
2555          // Foldable operators
2556          case BOOLEAN_NOT_opcode:
2557          case INT_NOT_opcode:
2558          case REF_NOT_opcode:
2559          case LONG_NOT_opcode:
2560    
2561          case INT_NEG_opcode:
2562          case REF_NEG_opcode:
2563          case LONG_NEG_opcode:
2564          case FLOAT_NEG_opcode:
2565          case DOUBLE_NEG_opcode:
2566    
2567          case INT_2BYTE_opcode:
2568          case INT_2SHORT_opcode:
2569          case INT_2USHORT_opcode:
2570          case INT_2LONG_opcode:
2571          case LONG_2INT_opcode:
2572          case FLOAT_2DOUBLE_opcode:
2573          case DOUBLE_2FLOAT_opcode: {
2574            Operand val1 = Unary.getVal(s);
2575            // if val1 is constant too, this should've been constant folded
2576            // beforehand. Give up.
2577            if (val1.isConstant()) {
2578              return null;
2579            }
2580            Register result = Unary.getResult(s).asRegister().getRegister();
2581            if (ssa) {
2582              return result;
2583            } else if (val1.asRegister().getRegister() != result) {
2584              return result;
2585            } else {
2586              return null;
2587            }
2588          }
2589    
2590          case ARRAYLENGTH_opcode: {
2591            Operand val1 = GuardedUnary.getVal(s);
2592            // if val1 is constant too, this should've been constant folded
2593            // beforehand. Give up.
2594            if (val1.isConstant()) {
2595              return null;
2596            }
2597            Register result = GuardedUnary.getResult(s).asRegister().getRegister();
2598            // don't worry about the input and output bring the same as their types differ
2599            return result;
2600          }
2601    
2602          case INT_ADD_opcode:
2603          case REF_ADD_opcode:
2604          case LONG_ADD_opcode:
2605          case FLOAT_ADD_opcode:
2606          case DOUBLE_ADD_opcode:
2607    
2608          case INT_SUB_opcode:
2609          case REF_SUB_opcode:
2610          case LONG_SUB_opcode:
2611          case FLOAT_SUB_opcode:
2612          case DOUBLE_SUB_opcode:
2613    
2614          case INT_MUL_opcode:
2615          case LONG_MUL_opcode:
2616          case FLOAT_MUL_opcode:
2617          case DOUBLE_MUL_opcode:
2618    
2619          case FLOAT_DIV_opcode:
2620          case DOUBLE_DIV_opcode:
2621    
2622          case INT_SHL_opcode:
2623          case REF_SHL_opcode:
2624          case LONG_SHL_opcode:
2625    
2626          case INT_SHR_opcode:
2627          case REF_SHR_opcode:
2628          case LONG_SHR_opcode:
2629    
2630          case INT_USHR_opcode:
2631          case REF_USHR_opcode:
2632          case LONG_USHR_opcode:
2633    
2634          case INT_AND_opcode:
2635          case REF_AND_opcode:
2636          case LONG_AND_opcode:
2637    
2638          case INT_OR_opcode:
2639          case REF_OR_opcode:
2640          case LONG_OR_opcode:
2641    
2642          case INT_XOR_opcode:
2643          case REF_XOR_opcode:
2644          case LONG_XOR_opcode:
2645    
2646          case LONG_CMP_opcode:
2647          case FLOAT_CMPL_opcode:
2648          case DOUBLE_CMPL_opcode:
2649          case FLOAT_CMPG_opcode:
2650          case DOUBLE_CMPG_opcode: {
2651    
2652            Operand val2 = Binary.getVal2(s);
2653            if (!val2.isObjectConstant() && !val2.isTIBConstant()) {
2654              if (val2.isConstant()) {
2655                Operand val1 = Binary.getVal1(s);
2656                // if val1 is constant too, this should've been constant folded
2657                // beforehand. Give up.
2658                if (val1.isConstant()) {
2659                  return null;
2660                }
2661    
2662                Register result = Binary.getResult(s).asRegister().getRegister();
2663                if (ssa) {
2664                  return result;
2665                } else if (val1.asRegister().getRegister() != result) {
2666                  return result;
2667                } else {
2668                  return null;
2669                }
2670              } else {
2671                if (VM.VerifyAssertions) {
2672                  VM._assert(val2.isRegister());
2673                }
2674    
2675                Operand val1 = Binary.getVal1(s);
2676                if (s.operator.isCommutative() && val1.isConstant() && !val1.isMovableObjectConstant() && !val1.isTIBConstant()) {
2677                  Binary.setVal1(s, Binary.getClearVal2(s));
2678                  Binary.setVal2(s, val1);
2679                  Register result = Binary.getResult(s).asRegister().getRegister();
2680                  if (ssa) {
2681                    return result;
2682                  } else if (val2.asRegister().getRegister() != result) {
2683                    return result;
2684                  } else {
2685                    return null;
2686                  }
2687                }
2688              }
2689            }
2690            return null;
2691          }
2692    
2693          case INT_DIV_opcode:
2694          case LONG_DIV_opcode: {
2695            Operand val2 = GuardedBinary.getVal2(s);
2696            if (val2.isConstant()) {
2697              Operand val1 = GuardedBinary.getVal1(s);
2698              // if val1 is constant too, this should've been constant folded
2699              // beforehand. Give up.
2700              if (val1.isConstant()) {
2701                return null;
2702              }
2703              Register result = GuardedBinary.getResult(s).asRegister().getRegister();
2704              if (ssa) {
2705                return result;
2706              } else if (val1.asRegister().getRegister() != result) {
2707                return result;
2708              }
2709            }
2710            return null;
2711          }
2712    
2713          case BOOLEAN_CMP_INT_opcode:
2714          case BOOLEAN_CMP_LONG_opcode:
2715          case BOOLEAN_CMP_ADDR_opcode: {
2716            Operand val2 = BooleanCmp.getVal2(s);
2717            if (val2.isConstant() && !val2.isMovableObjectConstant() && !val2.isTIBConstant()) {
2718              Operand val1 = BooleanCmp.getVal1(s);
2719              // if val1 is constant too, this should've been constant folded
2720              // beforehand. Give up.
2721              if (val1.isConstant()) {
2722                return null;
2723              }
2724              Register result = BooleanCmp.getResult(s).asRegister().getRegister();
2725              if (ssa) {
2726                return result;
2727              } else if (val1.asRegister().getRegister() != result) {
2728                return result;
2729              }
2730            } else if (val2.isRegister()) {
2731              Operand val1 = BooleanCmp.getVal1(s);
2732              if (val1.isConstant() && !val1.isMovableObjectConstant() && !val1.isTIBConstant()) {
2733                BooleanCmp.setVal1(s, BooleanCmp.getClearVal2(s));
2734                BooleanCmp.setVal2(s, val1);
2735                BooleanCmp.getCond(s).flipOperands();
2736                Register result = BooleanCmp.getResult(s).asRegister().getRegister();
2737                if (ssa) {
2738                  return result;
2739                } else if (val2.asRegister().getRegister() != result) {
2740                  return result;
2741                }
2742              }
2743            }
2744            return null;
2745          }
2746          case INT_IFCMP_opcode:
2747          case LONG_IFCMP_opcode:
2748          case FLOAT_IFCMP_opcode:
2749          case DOUBLE_IFCMP_opcode:
2750          case REF_IFCMP_opcode: {
2751            Operand val2 = IfCmp.getVal2(s);
2752            if (!val2.isObjectConstant() && !val2.isTIBConstant()) {
2753              if (val2.isConstant()) {
2754                Operand val1 = IfCmp.getVal1(s);
2755                // if val1 is constant too, this should've been constant folded
2756                // beforehand. Give up.
2757                if (val1.isConstant()) {
2758                  return null;
2759                }
2760    
2761                Register result = IfCmp.getGuardResult(s).asRegister().getRegister();
2762                if (ssa) {
2763                  return result;
2764                } else if (val1.asRegister().getRegister() != result) {
2765                  return result;
2766                }
2767              } else {
2768                if (VM.VerifyAssertions) {
2769                  VM._assert(val2.isRegister());
2770                }
2771                Operand val1 = IfCmp.getVal1(s);
2772                if (val1.isConstant() && !val1.isMovableObjectConstant() && !val1.isTIBConstant()) {
2773                  IfCmp.setVal1(s, IfCmp.getClearVal2(s));
2774                  IfCmp.setVal2(s, val1);
2775                  IfCmp.getCond(s).flipOperands();
2776                  Register result = IfCmp.getGuardResult(s).asRegister().getRegister();
2777                  if (ssa) {
2778                    return result;
2779                  } else if (val2.asRegister().getRegister() != result) {
2780                    return result;
2781                  }
2782                }
2783              }
2784            }
2785            return null;
2786          }
2787          case INT_IFCMP2_opcode: {
2788            Operand val2 = IfCmp2.getVal2(s);
2789            if (!val2.isObjectConstant() && !val2.isTIBConstant()) {
2790              if (val2.isConstant()) {
2791                Operand val1 = IfCmp2.getVal1(s);
2792                // if val1 is constant too, this should've been constant folded
2793                // beforehand. Give up.
2794                if (val1.isConstant()) {
2795                  return null;
2796                }
2797    
2798                Register result = IfCmp2.getGuardResult(s).asRegister().getRegister();
2799                if (ssa) {
2800                  return result;
2801                } else if (val1.asRegister().getRegister() != result) {
2802                  return result;
2803                }
2804              } else {
2805                if (VM.VerifyAssertions) {
2806                  VM._assert(val2.isRegister());
2807                }
2808                Operand val1 = IfCmp2.getVal1(s);
2809                if (val1.isConstant() && !val1.isMovableObjectConstant() && !val1.isTIBConstant()) {
2810                  IfCmp2.setVal1(s, IfCmp2.getClearVal2(s));
2811                  IfCmp2.setVal2(s, val1);
2812                  IfCmp2.getCond1(s).flipOperands();
2813                  IfCmp2.getCond2(s).flipOperands();
2814                  Register result = IfCmp2.getGuardResult(s).asRegister().getRegister();
2815                  if (ssa) {
2816                    return result;
2817                  } else if (val2.asRegister().getRegister() != result) {
2818                    return result;
2819                  }
2820                }
2821              }
2822            }
2823            return null;
2824          }
2825          case INT_COND_MOVE_opcode:
2826          case LONG_COND_MOVE_opcode:
2827          case REF_COND_MOVE_opcode:
2828          case FLOAT_COND_MOVE_opcode:
2829          case DOUBLE_COND_MOVE_opcode:
2830          case GUARD_COND_MOVE_opcode: {
2831            Operand val2 = CondMove.getVal2(s);
2832            if (!val2.isObjectConstant()) {
2833              if (val2.isConstant()) {
2834                Operand val1 = CondMove.getVal1(s);
2835                // if val1 is constant too, this should've been constant folded
2836                // beforehand. Give up.
2837                if (val1.isConstant()) {
2838                  return null;
2839                }
2840                Register result = CondMove.getResult(s).asRegister().getRegister();
2841                if (ssa) {
2842                  return result;
2843                } else if (val1.asRegister().getRegister() != result) {
2844                  return result;
2845                }
2846              } else {
2847                if (VM.VerifyAssertions) {
2848                  VM._assert(val2.isRegister());
2849                }
2850                Operand val1 = CondMove.getVal1(s);
2851                if (val1.isConstant() && !val1.isMovableObjectConstant()) {
2852                  CondMove.setVal1(s, CondMove.getClearVal2(s));
2853                  CondMove.setVal2(s, val1);
2854                  CondMove.getCond(s).flipOperands();
2855                  Register result = CondMove.getResult(s).asRegister().getRegister();
2856                  if (ssa) {
2857                    return result;
2858                  } else if (val2.asRegister().getRegister() != result) {
2859                    return result;
2860                  }
2861                }
2862              }
2863            }
2864            return null;
2865          }
2866          case BOUNDS_CHECK_opcode: {
2867            Operand ref = BoundsCheck.getRef(s);
2868            Operand index = BoundsCheck.getIndex(s);
2869            if (index.isConstant()) {
2870              if (ref.isConstant()) {
2871                // this should have been constant folded. Give up.
2872                return null;
2873              }
2874              // don't worry about the input and output bring the same as their types differ
2875              return BoundsCheck.getGuardResult(s).asRegister().getRegister();
2876            }
2877            return null;
2878          }
2879          case NULL_CHECK_opcode: {
2880            Operand ref = NullCheck.getRef(s);
2881            if (ref.isConstant()) {
2882              // this should have been constant folded. Give up.
2883              return null;
2884            }
2885            // don't worry about the input and output bring the same as their types differ
2886            return NullCheck.getGuardResult(s).asRegister().getRegister();
2887          }
2888          case INSTANCEOF_opcode: {
2889            Operand ref = InstanceOf.getRef(s);
2890            if (ref.isConstant()) {
2891              // this should have been constant folded. Give up.
2892              return null;
2893            }
2894            // don't worry about the input and output bring the same as their types differ
2895            return InstanceOf.getResult(s).getRegister();
2896          }
2897          case NEWARRAY_opcode: {
2898            Operand size = NewArray.getSize(s);
2899            if (size.isConstant()) {
2900              // don't worry about the input and output bring the same as their types differ
2901              return NewArray.getResult(s).getRegister();
2902            }
2903            return null;
2904          }
2905          case NEW_opcode: {
2906            return New.getResult(s).getRegister();
2907          }
2908          case INT_ZERO_CHECK_opcode:
2909          case LONG_ZERO_CHECK_opcode:  {
2910            Operand val1 = ZeroCheck.getValue(s);
2911            // if val1 is constant, this should've been constant folded
2912            // beforehand. Give up.
2913            if (val1.isConstant()) {
2914              return null;
2915            }
2916            // don't worry about the input and output bring the same as their types differ
2917            return ZeroCheck.getGuardResult(s).asRegister().getRegister();
2918          }
2919          default:
2920            // Operator can't be folded
2921            return null;
2922        }
2923      }
2924    
2925      private static int getIntValue(Operand op) {
2926        if (op instanceof IntConstantOperand) {
2927          return op.asIntConstant().value;
2928        }
2929        if (VM.BuildFor32Addr) {
2930          return getAddressValue(op).toInt();
2931        }
2932        throw new OptimizingCompilerException(
2933            "Cannot getIntValue from this operand " + op +
2934            " of instruction " + op.instruction);
2935      }
2936    
2937      private static long getLongValue(Operand op) {
2938        if (op instanceof LongConstantOperand)
2939          return op.asLongConstant().value;
2940        if (VM.BuildFor64Addr) {
2941          return getAddressValue(op).toLong();
2942        }
2943        throw new OptimizingCompilerException(
2944            "Cannot getLongValue from this operand " + op +
2945            " of instruction " + op.instruction);
2946      }
2947    
2948      private static float getFloatValue(Operand op) {
2949        if (op instanceof FloatConstantOperand)
2950          return op.asFloatConstant().value;
2951        throw new OptimizingCompilerException(
2952            "Cannot getFloatValue from this operand " + op +
2953            " of instruction " + op.instruction);
2954      }
2955    
2956      private static double getDoubleValue(Operand op) {
2957        if (op instanceof DoubleConstantOperand)
2958          return op.asDoubleConstant().value;
2959        throw new OptimizingCompilerException(
2960            "Cannot getDoubleValue from this operand " + op +
2961            " of instruction " + op.instruction);
2962      }
2963    
2964      private static Address getAddressValue(Operand op) {
2965        if (op instanceof NullConstantOperand) {
2966          return Address.zero();
2967        }
2968        if (op instanceof AddressConstantOperand) {
2969          return op.asAddressConstant().value;
2970        }
2971        if (op instanceof IntConstantOperand) {
2972          return Address.fromIntSignExtend(op.asIntConstant().value);
2973        }
2974        if (VM.BuildFor64Addr && op instanceof LongConstantOperand) {
2975          return Address.fromLong(op.asLongConstant().value);
2976        }
2977        if (op instanceof ObjectConstantOperand) {
2978          if (VM.VerifyAssertions) VM._assert(!op.isMovableObjectConstant());
2979          return Magic.objectAsAddress(op.asObjectConstant().value);
2980        }
2981        throw new OptimizingCompilerException(
2982            "Cannot getAddressValue from this operand " + op +
2983            " of instruction " + op.instruction);
2984      }
2985    }