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