Search in sources :

Example 11 with BranchOperand

use of org.jikesrvm.compilers.opt.ir.operand.BranchOperand in project JikesRVM by JikesRVM.

the class Diamond method fourElementDiamond.

private static Diamond fourElementDiamond(BasicBlock top, BasicBlock left, BasicBlock right, BasicBlock bottom) {
    Instruction cb = top.firstBranchInstruction();
    // for now we only support IfCmp diamonds.
    if (VM.VerifyAssertions)
        VM._assert(IfCmp.conforms(cb));
    BranchOperand takenTarget = IfCmp.getTarget(cb);
    if (Label.getBlock(takenTarget.target).block == left) {
        return new Diamond(top, left, right, bottom);
    } else {
        return new Diamond(top, right, left, bottom);
    }
}
Also used : Instruction(org.jikesrvm.compilers.opt.ir.Instruction) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand)

Example 12 with BranchOperand

use of org.jikesrvm.compilers.opt.ir.operand.BranchOperand in project JikesRVM by JikesRVM.

the class ComplexLIR2MIRExpansion method fp_ifcmp.

// the fcmoi/fcmoip was generated by burs
// we do the rest of the expansion here because in some
// cases we must remove a trailing goto, and we
// can't do that in burs!
private static Instruction fp_ifcmp(Instruction s) {
    Instruction nextInstr = s.nextInstructionInCodeOrder();
    BranchOperand testFailed;
    BasicBlock bb = s.getBasicBlock();
    Instruction lastInstr = bb.lastRealInstruction();
    if (lastInstr.operator() == IA32_JMP) {
        // We're in trouble if there is another instruction between s and lastInstr!
        if (VM.VerifyAssertions)
            VM._assert(s.nextInstructionInCodeOrder() == lastInstr);
        // Set testFailed to target of GOTO
        testFailed = MIR_Branch.getClearTarget(lastInstr);
        nextInstr = lastInstr.nextInstructionInCodeOrder();
        lastInstr.remove();
    } else {
        // Set testFailed to label of next (fallthrough basic block)
        testFailed = bb.nextBasicBlockInCodeOrder().makeJumpTarget();
    }
    // Translate condition operand respecting IA32 FCOMI/COMISS/COMISD
    Instruction fcomi = s.prevInstructionInCodeOrder();
    Operand val1 = MIR_Compare.getVal1(fcomi);
    Operand val2 = MIR_Compare.getVal2(fcomi);
    ConditionOperand c = IfCmp.getCond(s);
    BranchOperand target = IfCmp.getTarget(s).copy().asBranch();
    BranchProfileOperand branchProfile = (BranchProfileOperand) IfCmp.getBranchProfile(s).copy();
    // propagate the original probability to the second condition.
    switch(c.value) {
        // (i.e. UNORDERED is a goto to testFailed)
        case ConditionOperand.CMPL_EQUAL:
            if (VM.VerifyAssertions)
                VM._assert(!c.branchIfUnordered());
            // Check whether val1 and val2 operands are the same
            if (!val1.similar(val2)) {
                s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, IA32ConditionOperand.PE(), // PF == 1
                testFailed, new BranchProfileOperand(0f), IA32ConditionOperand.EQ(), // ZF == 1
                target, branchProfile));
                s.insertBefore(MIR_Branch.create(IA32_JMP, (BranchOperand) (testFailed.copy())));
            } else {
                // As val1 == val2 result of compare must be == or UNORDERED
                s.insertBefore(// PF == 0
                MIR_CondBranch.create(// PF == 0
                IA32_JCC, // PF == 0
                IA32ConditionOperand.PO(), target, branchProfile));
                s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
            }
            break;
        case ConditionOperand.CMPL_GREATER:
            if (VM.VerifyAssertions)
                VM._assert(!c.branchIfUnordered());
            s.insertBefore(// CF == 0 and ZF == 0
            MIR_CondBranch.create(// CF == 0 and ZF == 0
            IA32_JCC, // CF == 0 and ZF == 0
            IA32ConditionOperand.LGT(), target, branchProfile));
            s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
            break;
        case ConditionOperand.CMPG_LESS:
            if (VM.VerifyAssertions)
                VM._assert(!c.branchIfUnordered());
            s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, IA32ConditionOperand.PE(), // PF == 1
            testFailed, new BranchProfileOperand(0f), IA32ConditionOperand.LLT(), // CF == 1
            target, branchProfile));
            s.insertBefore(MIR_Branch.create(IA32_JMP, (BranchOperand) (testFailed.copy())));
            break;
        case ConditionOperand.CMPL_GREATER_EQUAL:
            if (VM.VerifyAssertions)
                VM._assert(!c.branchIfUnordered());
            s.insertBefore(// CF == 0
            MIR_CondBranch.create(// CF == 0
            IA32_JCC, // CF == 0
            IA32ConditionOperand.LGE(), target, branchProfile));
            s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
            break;
        case ConditionOperand.CMPG_LESS_EQUAL:
            s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, IA32ConditionOperand.PE(), // PF == 1
            testFailed, new BranchProfileOperand(0f), IA32ConditionOperand.LGT(), // ZF == 0 and CF == 0
            (BranchOperand) (testFailed.copy()), branchProfile));
            s.insertBefore(MIR_Branch.create(IA32_JMP, target));
            break;
        // (i.e. UNORDERED is a goto to target)
        case ConditionOperand.CMPL_NOT_EQUAL:
            if (VM.VerifyAssertions)
                VM._assert(c.branchIfUnordered());
            // Check whether val1 and val2 operands are the same
            if (!val1.similar(val2)) {
                s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, IA32ConditionOperand.PE(), // PF == 1
                target, new BranchProfileOperand(0f), IA32ConditionOperand.NE(), // ZF == 0
                (BranchOperand) (target.copy()), branchProfile));
                s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
            } else {
                // As val1 == val2 result of compare must be == or UNORDERED
                s.insertBefore(// PF == 1
                MIR_CondBranch.create(// PF == 1
                IA32_JCC, // PF == 1
                IA32ConditionOperand.PE(), target, branchProfile));
                s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
            }
            break;
        case ConditionOperand.CMPL_LESS:
            if (VM.VerifyAssertions)
                VM._assert(c.branchIfUnordered());
            s.insertBefore(// CF == 1
            MIR_CondBranch.create(// CF == 1
            IA32_JCC, // CF == 1
            IA32ConditionOperand.LLT(), target, branchProfile));
            s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
            break;
        case ConditionOperand.CMPG_GREATER_EQUAL:
            if (VM.VerifyAssertions)
                VM._assert(c.branchIfUnordered());
            s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, IA32ConditionOperand.PE(), // PF == 1
            target, new BranchProfileOperand(0f), IA32ConditionOperand.LLT(), // CF == 1
            testFailed, branchProfile));
            s.insertBefore(MIR_Branch.create(IA32_JMP, (BranchOperand) (target.copy())));
            break;
        case ConditionOperand.CMPG_GREATER:
            if (VM.VerifyAssertions)
                VM._assert(c.branchIfUnordered());
            s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, IA32ConditionOperand.PE(), // PF == 1
            target, new BranchProfileOperand(0f), IA32ConditionOperand.LGT(), // ZF == 0 and CF == 0
            (BranchOperand) (target.copy()), branchProfile));
            s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
            break;
        case ConditionOperand.CMPL_LESS_EQUAL:
            if (VM.VerifyAssertions)
                VM._assert(c.branchIfUnordered());
            s.insertBefore(// CF == 1 or ZF == 1
            MIR_CondBranch.create(// CF == 1 or ZF == 1
            IA32_JCC, // CF == 1 or ZF == 1
            IA32ConditionOperand.LLE(), target, branchProfile));
            s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
            break;
        default:
            OptimizingCompilerException.UNREACHABLE();
    }
    s.remove();
    return nextInstr;
}
Also used : LongConstantOperand(org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) IA32ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ia32.IA32ConditionOperand) StackLocationOperand(org.jikesrvm.compilers.opt.ir.operand.StackLocationOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) MemoryOperand(org.jikesrvm.compilers.opt.ir.operand.MemoryOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) IA32ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ia32.IA32ConditionOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand)

Example 13 with BranchOperand

use of org.jikesrvm.compilers.opt.ir.operand.BranchOperand in project JikesRVM by JikesRVM.

the class ExpressionFolding method transform.

/**
 * Perform the transformation on the instruction
 *
 * @param s
 *          the instruction to transform of the form y = x op c1
 * @param def
 *          the definition of x, the defining instruction is of the form x = a
 *          op c2
 * @return the new instruction to replace s;
 */
private static Instruction transform(Instruction s, Instruction def) {
    // x = a op1 c1  <-- def
    // y = x op2 c2  <-- s
    final RegisterOperand a = getUseFromCandidate(def);
    final RegisterOperand x = getDefFromCandidate(def, true);
    if (x == null) {
        return null;
    }
    final RegisterOperand y = getDefFromCandidate(s, false);
    if (y == null) {
        return null;
    }
    if (VM.VerifyAssertions) {
        RegisterOperand x2;
        x2 = getUseFromCandidate(s);
        boolean similar = x.similar(x2);
        if (!similar) {
            String msg = "x not similar to x2 " + x + " : " + x2;
            VM._assert(VM.NOT_REACHED, msg);
        }
    }
    switch(s.getOpcode()) {
        // Foldable operators
        case INT_ADD_opcode:
            {
                if (FOLD_INTS && FOLD_ADDS) {
                    int c2 = getIntValue(Binary.getVal2(s));
                    if (def.operator() == INT_ADD) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a + c1; y = x + c2
                        return Binary.create(INT_ADD, y.copyRO(), a.copyRO(), IC(c1 + c2));
                    } else if (def.operator() == INT_SUB) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a - c1; y = x + c2
                        return Binary.create(INT_ADD, y.copyRO(), a.copyRO(), IC(c2 - c1));
                    } else if (def.operator() == INT_NEG && FOLD_CONSTANTS_TO_LHS) {
                        // x = -a; y = x + c2;
                        return Binary.create(INT_SUB, y.copyRO(), IC(c2), a.copyRO());
                    }
                }
                return null;
            }
        case REF_ADD_opcode:
            {
                if (FOLD_REFS && FOLD_ADDS) {
                    Address c2 = getAddressValue(Binary.getVal2(s));
                    if (def.operator() == REF_ADD) {
                        Address c1 = getAddressValue(Binary.getVal2(def));
                        // x = a + c1; y = x + c2
                        return Binary.create(REF_ADD, y.copyRO(), a.copyRO(), AC(c1.toWord().plus(c2.toWord()).toAddress()));
                    } else if (def.operator() == REF_SUB) {
                        Address c1 = getAddressValue(Binary.getVal2(def));
                        // x = a - c1; y = x + c2
                        return Binary.create(REF_ADD, y.copyRO(), a.copyRO(), AC(c2.toWord().minus(c1.toWord()).toAddress()));
                    } else if (def.operator() == REF_NEG && FOLD_CONSTANTS_TO_LHS) {
                        // x = -a; y = x + c2;
                        return Binary.create(REF_SUB, y.copyRO(), AC(c2), a.copyRO());
                    }
                }
                return null;
            }
        case LONG_ADD_opcode:
            {
                if (FOLD_LONGS && FOLD_ADDS) {
                    long c2 = getLongValue(Binary.getVal2(s));
                    if (def.operator() == LONG_ADD) {
                        long c1 = getLongValue(Binary.getVal2(def));
                        // x = a + c1; y = x + c2
                        return Binary.create(LONG_ADD, y.copyRO(), a.copyRO(), LC(c1 + c2));
                    } else if (def.operator() == LONG_SUB) {
                        long c1 = getLongValue(Binary.getVal2(def));
                        // x = a - c1; y = x + c2
                        return Binary.create(LONG_ADD, y.copyRO(), a.copyRO(), LC(c2 - c1));
                    } else if (def.operator() == LONG_NEG && FOLD_CONSTANTS_TO_LHS) {
                        // x = -a; y = x + c2;
                        return Binary.create(LONG_SUB, y.copyRO(), LC(c2), a.copyRO());
                    }
                }
                return null;
            }
        case FLOAT_ADD_opcode:
            {
                if (FOLD_FLOATS && FOLD_ADDS) {
                    float c2 = getFloatValue(Binary.getVal2(s));
                    if (def.operator() == FLOAT_ADD) {
                        float c1 = getFloatValue(Binary.getVal2(def));
                        // x = a + c1; y = x + c2
                        return Binary.create(FLOAT_ADD, y.copyRO(), a.copyRO(), FC(c1 + c2));
                    } else if (def.operator() == FLOAT_SUB) {
                        float c1 = getFloatValue(Binary.getVal2(def));
                        // x = a - c1; y = x + c2
                        return Binary.create(FLOAT_ADD, y.copyRO(), a.copyRO(), FC(c2 - c1));
                    } else if (def.operator() == FLOAT_NEG && FOLD_CONSTANTS_TO_LHS) {
                        // x = -a; y = x + c2;
                        return Binary.create(FLOAT_SUB, y.copyRO(), FC(c2), a.copyRO());
                    }
                }
                return null;
            }
        case DOUBLE_ADD_opcode:
            {
                if (FOLD_DOUBLES && FOLD_ADDS) {
                    double c2 = getDoubleValue(Binary.getVal2(s));
                    if (def.operator() == DOUBLE_ADD) {
                        double c1 = getDoubleValue(Binary.getVal2(def));
                        // x = a + c1; y = x + c2
                        return Binary.create(DOUBLE_ADD, y.copyRO(), a.copyRO(), DC(c1 + c2));
                    } else if (def.operator() == DOUBLE_SUB) {
                        double c1 = getDoubleValue(Binary.getVal2(def));
                        // x = a - c1; y = x + c2
                        return Binary.create(DOUBLE_ADD, y.copyRO(), a.copyRO(), DC(c2 - c1));
                    } else if (def.operator() == DOUBLE_NEG && FOLD_CONSTANTS_TO_LHS) {
                        // x = -a; y = x + c2;
                        return Binary.create(DOUBLE_SUB, y.copyRO(), DC(c2), a.copyRO());
                    }
                }
                return null;
            }
        case INT_SUB_opcode:
            {
                if (FOLD_INTS && FOLD_SUBS) {
                    int c2 = getIntValue(Binary.getVal2(s));
                    if (def.operator() == INT_ADD) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a + c1; y = x - c2
                        return Binary.create(INT_ADD, y.copyRO(), a.copyRO(), IC(c1 - c2));
                    } else if (def.operator() == INT_SUB) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a - c1; y = x - c2
                        return Binary.create(INT_ADD, y.copyRO(), a.copyRO(), IC(-c1 - c2));
                    } else if (def.operator() == INT_NEG && FOLD_CONSTANTS_TO_LHS) {
                        // x = -a; y = x - c2;
                        return Binary.create(INT_SUB, y.copyRO(), IC(-c2), a.copyRO());
                    }
                }
                return null;
            }
        case REF_SUB_opcode:
            {
                if (FOLD_REFS && FOLD_SUBS) {
                    Address c2 = getAddressValue(Binary.getVal2(s));
                    if (def.operator() == REF_ADD) {
                        Address c1 = getAddressValue(Binary.getVal2(def));
                        // x = a + c1; y = x - c2
                        return Binary.create(REF_ADD, y.copyRO(), a.copyRO(), AC(c1.toWord().minus(c2.toWord()).toAddress()));
                    } else if (def.operator() == REF_SUB) {
                        Address c1 = getAddressValue(Binary.getVal2(def));
                        // x = a - c1; y = x - c2
                        return Binary.create(REF_ADD, y.copyRO(), a.copyRO(), AC(Word.zero().minus(c1.toWord()).minus(c2.toWord()).toAddress()));
                    } else if (def.operator() == REF_NEG && FOLD_CONSTANTS_TO_LHS) {
                        // x = -a; y = x - c2;
                        return Binary.create(REF_SUB, y.copyRO(), AC(Word.zero().minus(c2.toWord()).toAddress()), a.copyRO());
                    }
                }
                return null;
            }
        case LONG_SUB_opcode:
            {
                if (FOLD_LONGS && FOLD_SUBS) {
                    long c2 = getLongValue(Binary.getVal2(s));
                    if (def.operator() == LONG_ADD) {
                        long c1 = getLongValue(Binary.getVal2(def));
                        // x = a + c1; y = x - c2
                        return Binary.create(LONG_ADD, y.copyRO(), a.copyRO(), LC(c1 - c2));
                    } else if (def.operator() == LONG_SUB) {
                        long c1 = getLongValue(Binary.getVal2(def));
                        // x = a - c1; y = x - c2
                        return Binary.create(LONG_ADD, y.copyRO(), a.copyRO(), LC(-c1 - c2));
                    } else if (def.operator() == LONG_NEG && FOLD_CONSTANTS_TO_LHS) {
                        // x = -a; y = x - c2;
                        return Binary.create(LONG_SUB, y.copyRO(), LC(-c2), a.copyRO());
                    }
                }
                return null;
            }
        case FLOAT_SUB_opcode:
            {
                if (FOLD_FLOATS && FOLD_SUBS) {
                    float c2 = getFloatValue(Binary.getVal2(s));
                    if (def.operator() == FLOAT_ADD) {
                        float c1 = getFloatValue(Binary.getVal2(def));
                        // x = a + c1; y = x - c2
                        return Binary.create(FLOAT_ADD, y.copyRO(), a.copyRO(), FC(c1 - c2));
                    } else if (def.operator() == FLOAT_SUB) {
                        float c1 = getFloatValue(Binary.getVal2(def));
                        // x = a - c1; y = x - c2
                        return Binary.create(FLOAT_ADD, y.copyRO(), a.copyRO(), FC(-c1 - c2));
                    } else if (def.operator() == FLOAT_NEG && FOLD_CONSTANTS_TO_LHS) {
                        // x = -a; y = x - c2;
                        return Binary.create(FLOAT_SUB, y.copyRO(), FC(-c2), a.copyRO());
                    }
                }
                return null;
            }
        case DOUBLE_SUB_opcode:
            {
                if (FOLD_DOUBLES && FOLD_SUBS) {
                    double c2 = getDoubleValue(Binary.getVal2(s));
                    if (def.operator() == FLOAT_ADD) {
                        double c1 = getDoubleValue(Binary.getVal2(def));
                        // x = a + c1; y = x - c2
                        return Binary.create(DOUBLE_ADD, y.copyRO(), a.copyRO(), DC(c1 - c2));
                    } else if (def.operator() == DOUBLE_SUB) {
                        double c1 = getDoubleValue(Binary.getVal2(def));
                        // x = a - c1; y = x + c2
                        return Binary.create(DOUBLE_ADD, y.copyRO(), a.copyRO(), DC(-c1 - c2));
                    } else if (def.operator() == DOUBLE_NEG && FOLD_CONSTANTS_TO_LHS) {
                        // x = -a; y = x - c2;
                        return Binary.create(DOUBLE_SUB, y.copyRO(), DC(-c2), a.copyRO());
                    }
                }
                return null;
            }
        case INT_MUL_opcode:
            {
                if (FOLD_INTS && FOLD_MULTS) {
                    int c2 = getIntValue(Binary.getVal2(s));
                    if (def.operator() == INT_MUL) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a * c1; y = x * c2
                        return Binary.create(INT_MUL, y.copyRO(), a.copyRO(), IC(c1 * c2));
                    } else if (def.operator() == INT_NEG) {
                        // x = -a; y = x * c2;
                        return Binary.create(INT_MUL, y.copyRO(), a.copyRO(), IC(-c2));
                    }
                }
                return null;
            }
        case LONG_MUL_opcode:
            {
                if (FOLD_LONGS && FOLD_MULTS) {
                    long c2 = getLongValue(Binary.getVal2(s));
                    if (def.operator() == LONG_MUL) {
                        long c1 = getLongValue(Binary.getVal2(def));
                        // x = a * c1; y = x * c2
                        return Binary.create(LONG_MUL, y.copyRO(), a.copyRO(), LC(c1 * c2));
                    } else if (def.operator() == LONG_NEG) {
                        // x = -a; y = x * c2;
                        return Binary.create(LONG_MUL, y.copyRO(), a.copyRO(), LC(-c2));
                    }
                }
                return null;
            }
        case FLOAT_MUL_opcode:
            {
                if (FOLD_FLOATS && FOLD_MULTS) {
                    float c2 = getFloatValue(Binary.getVal2(s));
                    if (def.operator() == FLOAT_MUL) {
                        float c1 = getFloatValue(Binary.getVal2(def));
                        // x = a * c1; y = x * c2
                        return Binary.create(FLOAT_MUL, y.copyRO(), a.copyRO(), FC(c1 * c2));
                    } else if (def.operator() == FLOAT_NEG) {
                        // x = -a; y = x * c2;
                        return Binary.create(FLOAT_MUL, y.copyRO(), a.copyRO(), FC(-c2));
                    }
                }
                return null;
            }
        case DOUBLE_MUL_opcode:
            {
                if (FOLD_DOUBLES && FOLD_MULTS) {
                    double c2 = getDoubleValue(Binary.getVal2(s));
                    if (def.operator() == DOUBLE_MUL) {
                        double c1 = getDoubleValue(Binary.getVal2(def));
                        // x = a * c1; y = x * c2
                        return Binary.create(DOUBLE_MUL, y.copyRO(), a.copyRO(), DC(c1 * c2));
                    } else if (def.operator() == DOUBLE_NEG) {
                        // x = -a; y = x * c2;
                        return Binary.create(DOUBLE_MUL, y.copyRO(), a.copyRO(), DC(-c2));
                    }
                }
                return null;
            }
        case INT_DIV_opcode:
            {
                if (FOLD_INTS && FOLD_DIVS) {
                    int c2 = getIntValue(GuardedBinary.getVal2(s));
                    if (def.operator() == INT_DIV) {
                        int c1 = getIntValue(GuardedBinary.getVal2(def));
                        Operand guard = GuardedBinary.getGuard(def);
                        // x = a / c1; y = x / c2
                        return GuardedBinary.create(INT_DIV, y.copyRO(), a.copyRO(), IC(c1 * c2), guard);
                    } else if (def.operator() == INT_NEG) {
                        Operand guard = GuardedBinary.getGuard(s);
                        // x = -a; y = x / c2;
                        return GuardedBinary.create(INT_DIV, y.copyRO(), a.copyRO(), IC(-c2), guard);
                    }
                }
                return null;
            }
        case LONG_DIV_opcode:
            {
                if (FOLD_LONGS && FOLD_DIVS) {
                    long c2 = getLongValue(GuardedBinary.getVal2(s));
                    if (def.operator() == LONG_DIV) {
                        long c1 = getLongValue(GuardedBinary.getVal2(def));
                        Operand guard = GuardedBinary.getGuard(def);
                        // x = a / c1; y = x / c2
                        return GuardedBinary.create(LONG_DIV, y.copyRO(), a.copyRO(), LC(c1 * c2), guard);
                    } else if (def.operator() == LONG_NEG) {
                        Operand guard = GuardedBinary.getGuard(s);
                        // x = -a; y = x / c2;
                        return GuardedBinary.create(LONG_DIV, y.copyRO(), a.copyRO(), LC(-c2), guard);
                    }
                }
                return null;
            }
        case FLOAT_DIV_opcode:
            {
                if (FOLD_FLOATS && FOLD_DIVS) {
                    float c2 = getFloatValue(Binary.getVal2(s));
                    if (def.operator() == FLOAT_DIV) {
                        float c1 = getFloatValue(Binary.getVal2(def));
                        // x = a / c1; y = x / c2
                        return Binary.create(FLOAT_DIV, y.copyRO(), a.copyRO(), FC(c1 * c2));
                    } else if (def.operator() == FLOAT_NEG) {
                        // x = -a; y = x / c2;
                        return Binary.create(FLOAT_DIV, y.copyRO(), a.copyRO(), FC(-c2));
                    }
                }
                return null;
            }
        case DOUBLE_DIV_opcode:
            {
                if (FOLD_DOUBLES && FOLD_DIVS) {
                    double c2 = getDoubleValue(Binary.getVal2(s));
                    if (def.operator() == DOUBLE_DIV) {
                        double c1 = getDoubleValue(Binary.getVal2(def));
                        // x = a / c1; y = x / c2
                        return Binary.create(DOUBLE_DIV, y.copyRO(), a.copyRO(), DC(c1 * c2));
                    } else if (def.operator() == DOUBLE_NEG) {
                        // x = -a; y = x / c2;
                        return Binary.create(DOUBLE_DIV, y.copyRO(), a.copyRO(), DC(-c2));
                    }
                }
                return null;
            }
        case INT_SHL_opcode:
            {
                if (FOLD_INTS && FOLD_SHIFTLS) {
                    int c2 = getIntValue(Binary.getVal2(s));
                    if (def.operator() == INT_SHL) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a << c1; y = x << c2
                        return Binary.create(INT_SHL, y.copyRO(), a.copyRO(), IC(c1 + c2));
                    } else if ((def.operator() == INT_SHR) || (def.operator() == INT_USHR)) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        if (c1 == c2) {
                            // x = a >> c1; y = x << c1
                            return Binary.create(INT_AND, y.copyRO(), a.copyRO(), IC(-1 << c1));
                        }
                    } else if (def.operator() == INT_AND) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a & c1; y = << c2
                        if ((c1 << c2) == (-1 << c2)) {
                            // the first mask is redundant
                            return Binary.create(INT_SHL, y.copyRO(), a.copyRO(), IC(c2));
                        }
                    } else if ((def.operator() == INT_OR) || (def.operator() == INT_XOR)) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a | c1; y = << c2
                        if ((c1 << c2) == 0) {
                            // the first mask is redundant
                            return Binary.create(INT_SHL, y.copyRO(), a.copyRO(), IC(c2));
                        }
                    }
                }
                return null;
            }
        case REF_SHL_opcode:
            {
                if (FOLD_REFS && FOLD_SHIFTLS) {
                    int c2 = getIntValue(Binary.getVal2(s));
                    if (def.operator() == REF_SHL) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a << c1; y = x << c2
                        return Binary.create(REF_SHL, y.copyRO(), a.copyRO(), IC(c1 + c2));
                    } else if ((def.operator() == REF_SHR) || (def.operator() == REF_USHR)) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        if (c1 == c2) {
                            // x = a >> c1; y = x << c1
                            return Binary.create(REF_AND, y.copyRO(), a.copyRO(), AC(Word.zero().minus(Word.one()).lsh(c1).toAddress()));
                        }
                    } else if (def.operator() == REF_AND) {
                        Address c1 = getAddressValue(Binary.getVal2(def));
                        // x = a & c1; y = x << c2
                        if (c1.toWord().lsh(c2).EQ(Word.fromIntSignExtend(-1).lsh(c2))) {
                            // the first mask is redundant
                            return Binary.create(REF_SHL, y.copyRO(), a.copyRO(), IC(c2));
                        }
                    } else if ((def.operator() == REF_OR) || (def.operator() == REF_XOR)) {
                        Address c1 = getAddressValue(Binary.getVal2(def));
                        // x = a | c1; y = x << c2
                        if (c1.toWord().lsh(c2).EQ(Word.zero())) {
                            // the first mask is redundant
                            return Binary.create(REF_SHL, y.copyRO(), a.copyRO(), IC(c2));
                        }
                    }
                }
                return null;
            }
        case LONG_SHL_opcode:
            {
                if (FOLD_LONGS && FOLD_SHIFTLS) {
                    int c2 = getIntValue(Binary.getVal2(s));
                    if (def.operator() == LONG_SHL) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a << c1; y = x << c2
                        return Binary.create(LONG_SHL, y.copyRO(), a.copyRO(), IC(c1 + c2));
                    } else if ((def.operator() == LONG_SHR) || (def.operator() == LONG_USHR)) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        if (c1 == c2) {
                            // x = a >> c1; y = x << c1
                            return Binary.create(LONG_AND, y.copyRO(), a.copyRO(), LC(-1L << c1));
                        }
                    } else if (def.operator() == LONG_AND) {
                        long c1 = getLongValue(Binary.getVal2(def));
                        // x = a & c1; y = << c2
                        if ((c1 << c2) == (-1L << c2)) {
                            // the first mask is redundant
                            return Binary.create(LONG_SHL, y.copyRO(), a.copyRO(), IC(c2));
                        }
                    } else if ((def.operator() == LONG_OR) || (def.operator() == LONG_XOR)) {
                        long c1 = getLongValue(Binary.getVal2(def));
                        // x = a | c1; y = << c2
                        if ((c1 << c2) == 0L) {
                            // the first mask is redundant
                            return Binary.create(LONG_SHL, y.copyRO(), a.copyRO(), IC(c2));
                        }
                    }
                }
                return null;
            }
        case INT_SHR_opcode:
            {
                if (FOLD_INTS && FOLD_SHIFTRS) {
                    int c2 = getIntValue(Binary.getVal2(s));
                    if (def.operator() == INT_SHR) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a >> c1; y = x >> c2
                        return Binary.create(INT_SHR, y.copyRO(), a.copyRO(), IC(c1 + c2));
                    } else if (def.operator() == INT_SHL) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        if (c1 == c2) {
                            if (c1 == 24) {
                                // x = a << 24; y = x >> 24
                                return Unary.create(INT_2BYTE, y.copyRO(), a.copyRO());
                            } else if (c1 == 16) {
                                // x = a << 16; y = x >> 16
                                return Unary.create(INT_2SHORT, y.copyRO(), a.copyRO());
                            }
                        }
                    } else if (def.operator() == INT_AND) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a & c1; y = >> c2
                        if ((c1 >> c2) == -1) {
                            // the first mask is redundant
                            return Binary.create(INT_SHR, y.copyRO(), a.copyRO(), IC(c2));
                        }
                    } else if ((def.operator() == INT_OR) || (def.operator() == INT_XOR)) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a | c1; y = >> c2
                        if ((c1 >>> c2) == 0) {
                            // the first mask is redundant
                            return Binary.create(INT_SHR, y.copyRO(), a.copyRO(), IC(c2));
                        }
                    }
                }
                return null;
            }
        case REF_SHR_opcode:
            {
                if (FOLD_REFS && FOLD_SHIFTRS) {
                    int c2 = getIntValue(Binary.getVal2(s));
                    if (def.operator() == REF_SHR) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a >> c1; y = x >> c2
                        return Binary.create(REF_SHR, y.copyRO(), a.copyRO(), IC(c1 + c2));
                    } else if (def.operator() == REF_AND) {
                        Address c1 = getAddressValue(Binary.getVal2(def));
                        // x = a & c1; y = x >> c2
                        if (c1.toWord().rsha(c2).EQ(Word.zero().minus(Word.one()))) {
                            // the first mask is redundant
                            return Binary.create(REF_SHR, y.copyRO(), a.copyRO(), IC(c2));
                        }
                    } else if ((def.operator() == REF_OR) || (def.operator() == REF_XOR)) {
                        Address c1 = getAddressValue(Binary.getVal2(def));
                        // x = a | c1; y = x >> c2
                        if (c1.toWord().rshl(c2).EQ(Word.zero())) {
                            // the first mask is redundant
                            return Binary.create(REF_SHR, y.copyRO(), a.copyRO(), IC(c2));
                        }
                    }
                }
                return null;
            }
        case LONG_SHR_opcode:
            {
                if (FOLD_LONGS && FOLD_SHIFTRS) {
                    int c2 = getIntValue(Binary.getVal2(s));
                    if (def.operator() == LONG_SHR) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a >> c1; y = x >> c2
                        return Binary.create(LONG_SHR, y.copyRO(), a.copyRO(), IC(c1 + c2));
                    } else if (def.operator() == LONG_AND) {
                        long c1 = getLongValue(Binary.getVal2(def));
                        // x = a & c1; y = >> c2
                        if ((c1 >> c2) == -1L) {
                            // the first mask is redundant
                            return Binary.create(LONG_SHR, y.copyRO(), a.copyRO(), IC(c2));
                        }
                    } else if ((def.operator() == LONG_OR) || (def.operator() == LONG_XOR)) {
                        long c1 = getLongValue(Binary.getVal2(def));
                        // x = a & c1; y = >> c2
                        if ((c1 >>> c2) == 0L) {
                            // the first mask is redundant
                            return Binary.create(LONG_SHR, y.copyRO(), a.copyRO(), IC(c2));
                        }
                    }
                }
                return null;
            }
        case INT_USHR_opcode:
            {
                if (FOLD_INTS && FOLD_SHIFTRS) {
                    int c2 = getIntValue(Binary.getVal2(s));
                    if (def.operator() == INT_USHR) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a >>> c1; y = x >>> c2
                        return Binary.create(INT_USHR, y.copyRO(), a.copyRO(), IC(c1 + c2));
                    } else if (def.operator() == INT_SHL) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        if (c1 == c2) {
                            // x = a << c1; y = x >>> c1
                            return Binary.create(INT_AND, y.copyRO(), a.copyRO(), IC(-1 >>> c1));
                        }
                    } else if (def.operator() == INT_AND) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a & c1; y = >>> c2
                        if ((c1 >> c2) == -1L) {
                            // the first mask is redundant
                            return Binary.create(INT_USHR, y.copyRO(), a.copyRO(), IC(c2));
                        }
                    } else if ((def.operator() == INT_OR) || (def.operator() == INT_XOR)) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a | c1; y = >>> c2
                        if ((c1 >>> c2) == 0) {
                            // the first mask is redundant
                            return Binary.create(INT_USHR, y.copyRO(), a.copyRO(), IC(c2));
                        }
                    }
                }
                return null;
            }
        case REF_USHR_opcode:
            {
                if (FOLD_REFS && FOLD_SHIFTRS) {
                    int c2 = getIntValue(Binary.getVal2(s));
                    if (def.operator() == REF_USHR) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a >>> c1; y = x >>> c2
                        return Binary.create(REF_USHR, y.copyRO(), a.copyRO(), IC(c1 + c2));
                    } else if (def.operator() == REF_SHL) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        if (c1 == c2) {
                            // x = a << c1; y = x >>> c1
                            return Binary.create(REF_AND, y.copyRO(), a.copyRO(), AC(Word.zero().minus(Word.one()).rshl(c1).toAddress()));
                        }
                    } else if (def.operator() == REF_AND) {
                        // IAN!!!
                        Address c1 = getAddressValue(Binary.getVal2(def));
                        // x = a & c1; y = x >>> c2
                        if (c1.toWord().rsha(c2).EQ(Word.zero().minus(Word.one()))) {
                            // the first mask is redundant
                            return Binary.create(REF_USHR, y.copyRO(), a.copyRO(), IC(c2));
                        }
                    } else if (false) {
                        // (def.operator() == REF_OR) || (def.operator() == REF_XOR)) {
                        Address c1 = getAddressValue(Binary.getVal2(def));
                        // x = a | c1; y = x >>> c2
                        if (c1.toWord().rshl(c2).EQ(Word.zero())) {
                            // the first mask is redundant
                            return Binary.create(REF_USHR, y.copyRO(), a.copyRO(), IC(c2));
                        }
                    }
                }
                return null;
            }
        case LONG_USHR_opcode:
            {
                if (FOLD_LONGS && FOLD_SHIFTRS) {
                    int c2 = getIntValue(Binary.getVal2(s));
                    if (def.operator() == LONG_USHR) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a >>> c1; y = x >>> c2
                        return Binary.create(LONG_USHR, y.copyRO(), a.copyRO(), IC(c1 + c2));
                    } else if (def.operator() == LONG_SHL) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        if (c1 == c2) {
                            // x = a << c1; y = x >>> c1
                            return Binary.create(LONG_AND, y.copyRO(), a.copyRO(), LC(-1L >>> c1));
                        }
                    } else if (def.operator() == LONG_AND) {
                        long c1 = getLongValue(Binary.getVal2(def));
                        // x = a & c1; y = >>> c2
                        if ((c1 >> c2) == -1L) {
                            // the first mask is redundant
                            return Binary.create(LONG_USHR, y.copyRO(), a.copyRO(), IC(c2));
                        }
                    } else if ((def.operator() == LONG_OR) || (def.operator() == LONG_XOR)) {
                        long c1 = getLongValue(Binary.getVal2(def));
                        // x = a & c1; y = >>> c2
                        if ((c1 >>> c2) == 0L) {
                            // the first mask is redundant
                            return Binary.create(LONG_USHR, y.copyRO(), a.copyRO(), IC(c2));
                        }
                    }
                }
                return null;
            }
        case INT_AND_opcode:
            {
                if (FOLD_INTS && FOLD_ANDS) {
                    int c2 = getIntValue(Binary.getVal2(s));
                    if (def.operator() == INT_AND) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a & c1; y = x & c2
                        return Binary.create(INT_AND, y.copyRO(), a.copyRO(), IC(c1 & c2));
                    } else if (def.operator() == INT_OR) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a | c1; y = x & c2
                        if ((c1 & c2) == 0) {
                            return Binary.create(INT_AND, y.copyRO(), a.copyRO(), IC(c2));
                        }
                    } else if (def.operator() == INT_XOR) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a ^ c1; y = x & c2
                        if ((c1 & c2) == 0) {
                            return Binary.create(INT_AND, y.copyRO(), a.copyRO(), IC(c2));
                        }
                    } else if (def.operator() == INT_SHR) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a >> c1; y = x & c2
                        if ((-1 >>> c1) == c2) {
                            // turn arithmetic shifts into logical shifts if possible
                            return Binary.create(INT_USHR, y.copyRO(), a.copyRO(), IC(c1));
                        }
                    } else if (def.operator() == INT_SHL) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a << c1; y = x & c2
                        if (((-1 << c1) & c2) == (-1 << c1)) {
                            // does the mask zero bits already cleared by the shift?
                            return Binary.create(INT_SHL, y.copyRO(), a.copyRO(), IC(c1));
                        }
                    } else if (def.operator() == INT_USHR) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a >>> c1; y = x & c2
                        if (((-1 >>> c1) & c2) == (-1 >>> c1)) {
                            // does the mask zero bits already cleared by the shift?
                            return Binary.create(INT_USHR, y.copyRO(), a.copyRO(), IC(c1));
                        }
                    }
                }
                return null;
            }
        case REF_AND_opcode:
            {
                if (FOLD_REFS && FOLD_ANDS) {
                    Address c2 = getAddressValue(Binary.getVal2(s));
                    if (def.operator() == REF_AND) {
                        Address c1 = getAddressValue(Binary.getVal2(def));
                        // x = a & c1; y = x & c2
                        return Binary.create(REF_AND, y.copyRO(), a.copyRO(), AC(c1.toWord().and(c2.toWord()).toAddress()));
                    } else if (def.operator() == REF_OR) {
                        Address c1 = getAddressValue(Binary.getVal2(def));
                        // x = a | c1; y = x & c2
                        if (c1.toWord().and(c2.toWord()).EQ(Word.zero())) {
                            return Binary.create(REF_AND, y.copyRO(), a.copyRO(), AC(c2));
                        }
                    } else if (def.operator() == REF_XOR) {
                        Address c1 = getAddressValue(Binary.getVal2(def));
                        // x = a ^ c1; y = x & c2
                        if (c1.toWord().and(c2.toWord()).EQ(Word.zero())) {
                            return Binary.create(REF_AND, y.copyRO(), a.copyRO(), AC(c2));
                        }
                    } else if (def.operator() == REF_SHR) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a >> c1; y = x & c2
                        if (Word.zero().minus(Word.one()).rshl(c1).toAddress().EQ(c2)) {
                            // turn arithmetic shifts into logical ones if possible
                            return Binary.create(REF_USHR, y.copyRO(), a.copyRO(), IC(c1));
                        }
                    } else if (def.operator() == REF_SHL) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a << c1; y = x & c2
                        if (Word.zero().minus(Word.one()).lsh(c1).and(c2.toWord()).EQ(Word.zero().minus(Word.one()).lsh(c1))) {
                            // does the mask zero bits already cleared by the shift?
                            return Binary.create(REF_SHL, y.copyRO(), a.copyRO(), IC(c1));
                        }
                    } else if (def.operator() == REF_USHR) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a >>> c1; y = x & c2
                        if (Word.zero().minus(Word.one()).rshl(c1).and(c2.toWord()).EQ(Word.zero().minus(Word.one()).rshl(c1))) {
                            // does the mask zero bits already cleared by the shift?
                            return Binary.create(REF_USHR, y.copyRO(), a.copyRO(), IC(c1));
                        }
                    }
                }
                return null;
            }
        case LONG_AND_opcode:
            {
                if (FOLD_LONGS && FOLD_ANDS) {
                    long c2 = getLongValue(Binary.getVal2(s));
                    if (def.operator() == LONG_AND) {
                        long c1 = getLongValue(Binary.getVal2(def));
                        // x = a & c1; y = x & c2
                        return Binary.create(LONG_AND, y.copyRO(), a.copyRO(), LC(c1 & c2));
                    } else if (def.operator() == LONG_OR) {
                        long c1 = getLongValue(Binary.getVal2(def));
                        // x = a | c1; y = x & c2
                        if ((c1 & c2) == 0) {
                            return Binary.create(LONG_AND, y.copyRO(), a.copyRO(), LC(c2));
                        }
                    } else if (def.operator() == LONG_XOR) {
                        long c1 = getLongValue(Binary.getVal2(def));
                        // x = a ^ c1; y = x & c2
                        if ((c1 & c2) == 0) {
                            return Binary.create(LONG_AND, y.copyRO(), a.copyRO(), LC(c2));
                        }
                    } else if (def.operator() == LONG_SHR) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a >> c1; y = x & c2
                        if ((-1L >>> c1) == c2) {
                            // turn arithmetic shifts into logical ones if possible
                            return Binary.create(LONG_USHR, y.copyRO(), a.copyRO(), IC(c1));
                        }
                    } else if (def.operator() == LONG_SHL) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a << c1; y = x & c2
                        if (((-1L << c1) & c2) == (-1L << c1)) {
                            // does the mask zero bits already cleared by the shift?
                            return Binary.create(LONG_SHL, y.copyRO(), a.copyRO(), IC(c1));
                        }
                    } else if (def.operator() == LONG_USHR) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a >>> c1; y = x & c2
                        if (((-1L >>> c1) & c2) == (-1L >>> c1)) {
                            // does the mask zero bits already cleared by the shift?
                            return Binary.create(LONG_USHR, y.copyRO(), a.copyRO(), IC(c1));
                        }
                    }
                }
                return null;
            }
        case INT_OR_opcode:
            {
                if (FOLD_INTS && FOLD_ORS) {
                    int c2 = getIntValue(Binary.getVal2(s));
                    if (def.operator() == INT_OR) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a | c1; y = x | c2
                        return Binary.create(INT_OR, y.copyRO(), a.copyRO(), IC(c1 | c2));
                    } else if (def.operator() == INT_AND) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a & c1; y = x | c2
                        if ((~c1 | c2) == c2) {
                            return Binary.create(INT_OR, y.copyRO(), a.copyRO(), IC(c2));
                        }
                    } else if (def.operator() == INT_XOR) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a ^ c1; y = x | c2
                        if ((c1 | c2) == c2) {
                            return Binary.create(INT_OR, y.copyRO(), a.copyRO(), IC(c2));
                        }
                    }
                }
                return null;
            }
        case REF_OR_opcode:
            {
                if (FOLD_REFS && FOLD_ORS) {
                    Address c2 = getAddressValue(Binary.getVal2(s));
                    if (def.operator() == REF_OR) {
                        Address c1 = getAddressValue(Binary.getVal2(def));
                        // x = a | c1; y = x | c2
                        return Binary.create(REF_OR, y.copyRO(), a.copyRO(), AC(c1.toWord().or(c2.toWord()).toAddress()));
                    } else if (def.operator() == REF_AND) {
                        Address c1 = getAddressValue(Binary.getVal2(def));
                        // x = a & c1; y = x | c2
                        if (c1.toWord().not().or(c2.toWord()).EQ(c2.toWord())) {
                            return Binary.create(REF_OR, y.copyRO(), a.copyRO(), AC(c2));
                        }
                    } else if (def.operator() == REF_XOR) {
                        Address c1 = getAddressValue(Binary.getVal2(def));
                        // x = a ^ c1; y = x | c2
                        if (c1.toWord().or(c2.toWord()).EQ(c2.toWord())) {
                            return Binary.create(REF_OR, y.copyRO(), a.copyRO(), AC(c2));
                        }
                    }
                }
                return null;
            }
        case LONG_OR_opcode:
            {
                if (FOLD_LONGS && FOLD_ORS) {
                    long c2 = getLongValue(Binary.getVal2(s));
                    if (def.operator() == LONG_OR) {
                        long c1 = getLongValue(Binary.getVal2(def));
                        // x = a | c1; y = x | c2
                        return Binary.create(LONG_OR, y.copyRO(), a.copyRO(), LC(c1 | c2));
                    } else if (def.operator() == LONG_AND) {
                        long c1 = getLongValue(Binary.getVal2(def));
                        // x = a & c1; y = x | c2
                        if ((~c1 | c2) == c2) {
                            return Binary.create(LONG_OR, y.copyRO(), a.copyRO(), LC(c2));
                        }
                    } else if (def.operator() == LONG_XOR) {
                        long c1 = getLongValue(Binary.getVal2(def));
                        // x = a ^ c1; y = x | c2
                        if ((c1 | c2) == c2) {
                            return Binary.create(LONG_OR, y.copyRO(), a.copyRO(), LC(c2));
                        }
                    }
                }
                return null;
            }
        case INT_XOR_opcode:
            {
                if (FOLD_INTS && FOLD_XORS) {
                    int c2 = getIntValue(Binary.getVal2(s));
                    if (def.operator() == INT_XOR) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a ^ c1; y = x ^ c2
                        return Binary.create(INT_XOR, y.copyRO(), a.copyRO(), IC(c1 ^ c2));
                    } else if (def.operator() == INT_NOT) {
                        // x = ~a; y = x ^ c2
                        return Binary.create(INT_XOR, y.copyRO(), a.copyRO(), IC(~c2));
                    } else if (def.operator() == BOOLEAN_NOT) {
                        // x = !a; y = x ^ c2
                        return Binary.create(INT_XOR, y.copyRO(), a.copyRO(), IC(c2 ^ 1));
                    }
                }
                return null;
            }
        case REF_XOR_opcode:
            {
                if (FOLD_REFS && FOLD_XORS) {
                    Address c2 = getAddressValue(Binary.getVal2(s));
                    if (def.operator() == REF_XOR) {
                        Address c1 = getAddressValue(Binary.getVal2(def));
                        // x = a ^ c1; y = x ^ c2
                        return Binary.create(REF_XOR, y.copyRO(), a.copyRO(), AC(c1.toWord().xor(c2.toWord()).toAddress()));
                    } else if (def.operator() == REF_NOT) {
                        // x = ~a; y = x ^ c2
                        return Binary.create(REF_XOR, y.copyRO(), a.copyRO(), AC(c2.toWord().not().toAddress()));
                    }
                }
                return null;
            }
        case LONG_XOR_opcode:
            {
                if (FOLD_LONGS && FOLD_XORS) {
                    long c2 = getLongValue(Binary.getVal2(s));
                    if (def.operator() == LONG_XOR) {
                        long c1 = getLongValue(Binary.getVal2(def));
                        // x = a ^ c1; y = x ^ c2
                        return Binary.create(LONG_XOR, y.copyRO(), a.copyRO(), LC(c1 ^ c2));
                    } else if (def.operator() == LONG_NOT) {
                        // x = ~a; y = x ^ c2
                        return Binary.create(LONG_XOR, y.copyRO(), a.copyRO(), LC(~c2));
                    }
                }
                return null;
            }
        case LONG_CMP_opcode:
            {
                if (FOLD_LONGS && FOLD_CMPS) {
                    long c2 = getLongValue(Binary.getVal2(s));
                    if (def.operator() == LONG_NEG) {
                        // x = -a; y = x cmp c2
                        return Binary.create(LONG_CMP, y.copyRO(), LC(-c2), a.copyRO());
                    }
                }
                return null;
            }
        case FLOAT_CMPL_opcode:
        case FLOAT_CMPG_opcode:
            {
                if (FOLD_FLOATS && FOLD_CMPS) {
                    float c2 = getFloatValue(Binary.getVal2(s));
                    if (def.operator() == FLOAT_ADD) {
                        float c1 = getFloatValue(Binary.getVal2(def));
                        // x = a + c1; y = x cmp c2
                        return Binary.create(s.operator(), y.copyRO(), a.copyRO(), FC(c2 - c1));
                    } else if (def.operator() == FLOAT_SUB) {
                        float c1 = getFloatValue(Binary.getVal2(def));
                        // x = a - c1; y = x cmp c2
                        return Binary.create(s.operator(), y.copyRO(), a.copyRO(), FC(c1 + c2));
                    } else if (def.operator() == FLOAT_NEG) {
                        // x = -a; y = x cmp c2
                        return Binary.create(s.operator(), y.copyRO(), FC(-c2), a.copyRO());
                    }
                }
                return null;
            }
        case DOUBLE_CMPL_opcode:
        case DOUBLE_CMPG_opcode:
            {
                if (FOLD_DOUBLES && FOLD_CMPS) {
                    double c2 = getDoubleValue(Binary.getVal2(s));
                    if (def.operator() == DOUBLE_ADD) {
                        double c1 = getDoubleValue(Binary.getVal2(def));
                        // x = a + c1; y = x cmp c2
                        return Binary.create(s.operator(), y.copyRO(), a.copyRO(), DC(c2 - c1));
                    } else if (def.operator() == DOUBLE_SUB) {
                        double c1 = getDoubleValue(Binary.getVal2(def));
                        // x = a - c1; y = x cmp c2
                        return Binary.create(s.operator(), y.copyRO(), a.copyRO(), DC(c1 + c2));
                    } else if (def.operator() == DOUBLE_NEG) {
                        // x = -a; y = x cmp c2
                        return Binary.create(s.operator(), y.copyRO(), DC(-c2), a.copyRO());
                    }
                }
                return null;
            }
        case BOOLEAN_CMP_INT_opcode:
            {
                if (FOLD_INTS && FOLD_CMPS) {
                    int c2 = getIntValue(BooleanCmp.getVal2(s));
                    ConditionOperand cond = (ConditionOperand) BooleanCmp.getCond(s).copy();
                    BranchProfileOperand prof = (BranchProfileOperand) BooleanCmp.getBranchProfile(s).copy();
                    if (cond.isEQUAL() || cond.isNOT_EQUAL()) {
                        if (def.operator() == INT_ADD) {
                            int c1 = getIntValue(Binary.getVal2(def));
                            // x = a + c1; y = x cmp c2
                            return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), IC(c2 - c1), cond, prof);
                        } else if (def.operator() == INT_SUB) {
                            int c1 = getIntValue(Binary.getVal2(def));
                            // x = a - c1; y = x cmp c2
                            return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), IC(c1 + c2), cond, prof);
                        } else if (def.operator() == INT_NEG) {
                            // x = -a; y = x cmp c2
                            return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), IC(-c2), cond.flipOperands(), prof);
                        } else if (def.operator() == BOOLEAN_CMP_INT) {
                            int c1 = getIntValue(BooleanCmp.getVal2(def));
                            ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
                            // x = a cmp c1 ? true : false; y = x cmp c2 ? true : false
                            if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
                                // Fold away redundancy boolean_cmp
                                return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), IC(c1), cond2, prof);
                            } else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
                                // Fold away redundancy boolean_cmp
                                return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), IC(c1), cond2.flipCode(), prof);
                            }
                        } else if (def.operator() == BOOLEAN_CMP_LONG) {
                            long c1 = getLongValue(BooleanCmp.getVal2(def));
                            ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
                            // x = a cmp c1 ? true : false; y = x cmp c2 ? true : false
                            if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
                                // Fold away redundancy boolean_cmp
                                return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), cond2, prof);
                            } else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
                                // Fold away redundancy boolean_cmp
                                return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), cond2.flipCode(), prof);
                            }
                        } else if (def.operator() == BOOLEAN_CMP_ADDR) {
                            Address c1 = getAddressValue(BooleanCmp.getVal2(def));
                            ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
                            // x = a cmp c1 ? true : false; y = x cmp c2 ? true : false
                            if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
                                // Fold away redundancy boolean_cmp
                                return BooleanCmp.create(BOOLEAN_CMP_ADDR, y.copyRO(), a.copyRO(), AC(c1), cond2, prof);
                            } else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
                                // Fold away redundancy boolean_cmp
                                return BooleanCmp.create(BOOLEAN_CMP_ADDR, y.copyRO(), a.copyRO(), AC(c1), cond2.flipCode(), prof);
                            }
                        } else if (def.operator() == BOOLEAN_CMP_FLOAT) {
                            float c1 = getFloatValue(BooleanCmp.getVal2(def));
                            ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
                            // x = a cmp c1 ? true : false; y = x cmp c2 ? true : false
                            if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
                                // Fold away redundancy boolean_cmp
                                return BooleanCmp.create(BOOLEAN_CMP_FLOAT, y.copyRO(), a.copyRO(), FC(c1), cond2, prof);
                            } else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
                                // Fold away redundancy boolean_cmp
                                return BooleanCmp.create(BOOLEAN_CMP_FLOAT, y.copyRO(), a.copyRO(), FC(c1), cond2.flipCode(), prof);
                            }
                        } else if (def.operator() == BOOLEAN_CMP_DOUBLE) {
                            double c1 = getDoubleValue(BooleanCmp.getVal2(def));
                            ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
                            // x = a cmp c1 ? true : false; y = x cmp c2 ? true : false
                            if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
                                // Fold away redundancy boolean_cmp
                                return BooleanCmp.create(BOOLEAN_CMP_DOUBLE, y.copyRO(), a.copyRO(), DC(c1), cond2, prof);
                            } else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
                                // Fold away redundancy boolean_cmp
                                return BooleanCmp.create(BOOLEAN_CMP_DOUBLE, y.copyRO(), a.copyRO(), DC(c1), cond2.flipCode(), prof);
                            }
                        } else if (def.operator() == LONG_CMP) {
                            long c1 = getLongValue(Binary.getVal2(def));
                            // x = a lcmp c1; y = y = x cmp c2 ? true : false
                            if (cond.isEQUAL() && c2 == 0) {
                                return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.EQUAL(), prof);
                            } else if (cond.isNOT_EQUAL() && c2 == 0) {
                                return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.NOT_EQUAL(), prof);
                            } else if ((cond.isEQUAL() && c2 == 1) || (cond.isGREATER() && c2 == 0)) {
                                return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.GREATER(), prof);
                            } else if (cond.isGREATER_EQUAL() && c2 == 0) {
                                return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.GREATER_EQUAL(), prof);
                            } else if ((cond.isEQUAL() && c2 == -1) || (cond.isLESS() && c2 == 0)) {
                                return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.LESS(), prof);
                            } else if (cond.isLESS_EQUAL() && c2 == 0) {
                                return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.LESS_EQUAL(), prof);
                            }
                        }
                    }
                }
                return null;
            }
        case BOOLEAN_CMP_LONG_opcode:
            {
                if (FOLD_LONGS && FOLD_CMPS) {
                    long c2 = getLongValue(BooleanCmp.getVal2(s));
                    ConditionOperand cond = (ConditionOperand) BooleanCmp.getCond(s).copy();
                    BranchProfileOperand prof = (BranchProfileOperand) BooleanCmp.getBranchProfile(s).copy();
                    if (cond.isEQUAL() || cond.isNOT_EQUAL()) {
                        if (def.operator() == LONG_ADD) {
                            long c1 = getLongValue(Binary.getVal2(def));
                            // x = a + c1; y = x cmp c2
                            return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c2 - c1), cond, prof);
                        } else if (def.operator() == LONG_SUB) {
                            long c1 = getLongValue(Binary.getVal2(def));
                            // x = a - c1; y = x cmp c2
                            return BooleanCmp.create(BOOLEAN_CMP_LONG, y.copyRO(), a.copyRO(), LC(c1 + c2), cond, prof);
                        } else if (def.operator() == LONG_NEG) {
                            // x = -a; y = x cmp c2
                            return BooleanCmp.create(BOOLEAN_CMP_INT, y.copyRO(), a.copyRO(), LC(-c2), cond.flipOperands(), prof);
                        }
                    }
                }
                return null;
            }
        case BOOLEAN_CMP_ADDR_opcode:
            {
                if (FOLD_REFS && FOLD_CMPS) {
                    Address c2 = getAddressValue(BooleanCmp.getVal2(s));
                    ConditionOperand cond = (ConditionOperand) BooleanCmp.getCond(s).copy();
                    BranchProfileOperand prof = (BranchProfileOperand) BooleanCmp.getBranchProfile(s).copy();
                    if (cond.isEQUAL() || cond.isNOT_EQUAL()) {
                        if (def.operator() == REF_ADD) {
                            Address c1 = getAddressValue(Binary.getVal2(def));
                            // x = a + c1; y = x cmp c2
                            return BooleanCmp.create(BOOLEAN_CMP_ADDR, y.copyRO(), a.copyRO(), AC(c2.toWord().minus(c1.toWord()).toAddress()), cond, prof);
                        } else if (def.operator() == REF_SUB) {
                            Address c1 = getAddressValue(Binary.getVal2(def));
                            // x = a - c1; y = x cmp c2
                            return BooleanCmp.create(BOOLEAN_CMP_ADDR, y.copyRO(), a.copyRO(), AC(c1.toWord().plus(c2.toWord()).toAddress()), cond, prof);
                        } else if (def.operator() == REF_NEG) {
                            // x = -a; y = x cmp c2
                            return BooleanCmp.create(BOOLEAN_CMP_ADDR, y.copyRO(), a.copyRO(), AC(Word.zero().minus(c2.toWord()).toAddress()), cond.flipOperands(), prof);
                        }
                    }
                }
                return null;
            }
        case INT_IFCMP_opcode:
            {
                if (FOLD_INTS && FOLD_IFCMPS) {
                    int c2 = getIntValue(IfCmp.getVal2(s));
                    ConditionOperand cond = (ConditionOperand) IfCmp.getCond(s).copy();
                    BranchOperand target = (BranchOperand) IfCmp.getTarget(s).copy();
                    BranchProfileOperand prof = (BranchProfileOperand) IfCmp.getBranchProfile(s).copy();
                    if (cond.isEQUAL() || cond.isNOT_EQUAL()) {
                        if (def.operator() == INT_ADD) {
                            int c1 = getIntValue(Binary.getVal2(def));
                            // x = a + c1; y = x cmp c2
                            return IfCmp.create(INT_IFCMP, y.copyRO(), a.copyRO(), IC(c2 - c1), cond, target, prof);
                        } else if (def.operator() == INT_SUB) {
                            int c1 = getIntValue(Binary.getVal2(def));
                            // x = a - c1; y = x cmp c2
                            return IfCmp.create(INT_IFCMP, y.copyRO(), a.copyRO(), IC(c1 + c2), cond, target, prof);
                        } else if (def.operator() == INT_NEG) {
                            // x = -a; y = x cmp c2
                            return IfCmp.create(INT_IFCMP, y.copyRO(), a.copyRO(), IC(-c2), cond.flipOperands(), target, prof);
                        } else if (def.operator() == BOOLEAN_CMP_INT) {
                            int c1 = getIntValue(BooleanCmp.getVal2(def));
                            ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
                            // x = a cmp<cond2> c1 ? true : false; y = x cmp<cond> c2
                            if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
                                // x = a cmp<cond2> c1; y = x == 1  ==> y = a cmp<cond2> c1
                                return IfCmp.create(INT_IFCMP, y.copyRO(), a.copyRO(), IC(c1), cond2, target, prof);
                            } else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
                                // x = a cmp<cond2> c1; y = x == 0  ==> y = a cmp<!cond2> c1
                                return IfCmp.create(INT_IFCMP, y.copyRO(), a.copyRO(), IC(c1), cond2.flipCode(), target, prof);
                            }
                        } else if (def.operator() == BOOLEAN_CMP_LONG) {
                            long c1 = getLongValue(BooleanCmp.getVal2(def));
                            ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
                            // x = a cmp c1 ? true : false; y = x cmp c2
                            if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
                                // Fold away redundant boolean_cmp
                                return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), cond2, target, prof);
                            } else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
                                // Fold away redundant boolean_cmp
                                return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), cond2.flipCode(), target, prof);
                            }
                        } else if (def.operator() == BOOLEAN_CMP_ADDR) {
                            Address c1 = getAddressValue(BooleanCmp.getVal2(def));
                            ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
                            // x = a cmp c1 ? true : false; y = x cmp c2
                            if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
                                // Fold away redundant boolean_cmp
                                return IfCmp.create(REF_IFCMP, y.copyRO(), a.copyRO(), AC(c1), cond2, target, prof);
                            } else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
                                // Fold away redundant boolean_cmp
                                return IfCmp.create(REF_IFCMP, y.copyRO(), a.copyRO(), AC(c1), cond2.flipCode(), target, prof);
                            }
                        } else if (def.operator() == BOOLEAN_CMP_FLOAT) {
                            float c1 = getFloatValue(BooleanCmp.getVal2(def));
                            ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
                            // x = a cmp c1 ? true : false; y = x cmp c2
                            if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
                                // Fold away redundant boolean_cmp
                                return IfCmp.create(FLOAT_IFCMP, y.copyRO(), a.copyRO(), FC(c1), cond2, target, prof);
                            } else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
                                // Fold away redundant boolean_cmp
                                return IfCmp.create(FLOAT_IFCMP, y.copyRO(), a.copyRO(), FC(c1), cond2.flipCode(), target, prof);
                            }
                        } else if (def.operator() == BOOLEAN_CMP_DOUBLE) {
                            double c1 = getDoubleValue(BooleanCmp.getVal2(def));
                            ConditionOperand cond2 = BooleanCmp.getCond(def).copy().asCondition();
                            // x = a cmp c1 ? true : false; y = x cmp c2
                            if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
                                // Fold away redundant boolean_cmp
                                return IfCmp.create(DOUBLE_IFCMP, y.copyRO(), a.copyRO(), DC(c1), cond2, target, prof);
                            } else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
                                // Fold away redundant boolean_cmp
                                return IfCmp.create(DOUBLE_IFCMP, y.copyRO(), a.copyRO(), DC(c1), cond2.flipCode(), target, prof);
                            }
                        } else if (def.operator() == LONG_CMP) {
                            long c1 = getLongValue(Binary.getVal2(def));
                            // x = a lcmp c1; y = y = x cmp c2
                            if (cond.isEQUAL() && c2 == 0) {
                                return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.EQUAL(), target, prof);
                            } else if (cond.isNOT_EQUAL() && c2 == 0) {
                                return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.NOT_EQUAL(), target, prof);
                            } else if ((cond.isEQUAL() && c2 == 1) || (cond.isGREATER() && c2 == 0)) {
                                return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.GREATER(), target, prof);
                            } else if (cond.isGREATER_EQUAL() && c2 == 0) {
                                return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.GREATER_EQUAL(), target, prof);
                            } else if ((cond.isEQUAL() && c2 == -1) || (cond.isLESS() && c2 == 0)) {
                                return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.LESS(), target, prof);
                            } else if (cond.isLESS_EQUAL() && c2 == 0) {
                                return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.LESS_EQUAL(), target, prof);
                            }
                        }
                    }
                }
                return null;
            }
        case LONG_IFCMP_opcode:
            {
                if (FOLD_LONGS && FOLD_IFCMPS) {
                    long c2 = getLongValue(IfCmp.getVal2(s));
                    ConditionOperand cond = (ConditionOperand) IfCmp.getCond(s).copy();
                    BranchOperand target = (BranchOperand) IfCmp.getTarget(s).copy();
                    BranchProfileOperand prof = (BranchProfileOperand) IfCmp.getBranchProfile(s).copy();
                    if (cond.isEQUAL() || cond.isNOT_EQUAL()) {
                        if (def.operator() == LONG_ADD) {
                            long c1 = getLongValue(Binary.getVal2(def));
                            // x = a + c1; y = x cmp c2
                            return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c2 - c1), cond, target, prof);
                        } else if (def.operator() == LONG_SUB) {
                            long c1 = getLongValue(Binary.getVal2(def));
                            // x = a - c1; y = x cmp c2
                            return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(c1 + c2), cond, target, prof);
                        } else if (def.operator() == LONG_NEG) {
                            // x = -a; y = x cmp c2
                            return IfCmp.create(LONG_IFCMP, y.copyRO(), a.copyRO(), LC(-c2), cond.flipOperands(), target, prof);
                        }
                    }
                }
                return null;
            }
        case FLOAT_IFCMP_opcode:
            {
                if (FOLD_FLOATS && FOLD_IFCMPS) {
                    float c2 = getFloatValue(IfCmp.getVal2(s));
                    ConditionOperand cond = (ConditionOperand) IfCmp.getCond(s).copy();
                    BranchOperand target = (BranchOperand) IfCmp.getTarget(s).copy();
                    BranchProfileOperand prof = (BranchProfileOperand) IfCmp.getBranchProfile(s).copy();
                    if (def.operator() == FLOAT_ADD) {
                        float c1 = getFloatValue(Binary.getVal2(def));
                        // x = a + c1; y = x cmp c2
                        return IfCmp.create(FLOAT_IFCMP, y.copyRO(), a.copyRO(), FC(c2 - c1), cond, target, prof);
                    } else if (def.operator() == FLOAT_SUB) {
                        float c1 = getFloatValue(Binary.getVal2(def));
                        // x = a - c1; y = x cmp c2
                        return IfCmp.create(FLOAT_IFCMP, y.copyRO(), a.copyRO(), FC(c1 + c2), cond, target, prof);
                    } else if (def.operator() == FLOAT_NEG) {
                        // x = -a; y = x cmp c2
                        return IfCmp.create(FLOAT_IFCMP, y.copyRO(), a.copyRO(), FC(-c2), cond.flipOperands(), target, prof);
                    }
                }
                return null;
            }
        case DOUBLE_IFCMP_opcode:
            {
                if (FOLD_DOUBLES && FOLD_IFCMPS) {
                    double c2 = getDoubleValue(IfCmp.getVal2(s));
                    ConditionOperand cond = (ConditionOperand) IfCmp.getCond(s).copy();
                    BranchOperand target = (BranchOperand) IfCmp.getTarget(s).copy();
                    BranchProfileOperand prof = (BranchProfileOperand) IfCmp.getBranchProfile(s).copy();
                    if (def.operator() == DOUBLE_ADD) {
                        double c1 = getDoubleValue(Binary.getVal2(def));
                        // x = a + c1; y = x cmp c2
                        return IfCmp.create(DOUBLE_IFCMP, y.copyRO(), a.copyRO(), DC(c2 - c1), cond, target, prof);
                    } else if (def.operator() == DOUBLE_SUB) {
                        double c1 = getDoubleValue(Binary.getVal2(def));
                        // x = a - c1; y = x cmp c2
                        return IfCmp.create(DOUBLE_IFCMP, y.copyRO(), a.copyRO(), DC(c1 + c2), cond, target, prof);
                    } else if (def.operator() == DOUBLE_NEG) {
                        // x = -a; y = x cmp c2
                        return IfCmp.create(DOUBLE_IFCMP, y.copyRO(), a.copyRO(), DC(-c2), cond.flipOperands(), target, prof);
                    }
                }
                return null;
            }
        case REF_IFCMP_opcode:
            {
                if (FOLD_REFS && FOLD_IFCMPS) {
                    Address c2 = getAddressValue(IfCmp.getVal2(s));
                    ConditionOperand cond = (ConditionOperand) IfCmp.getCond(s).copy();
                    BranchOperand target = (BranchOperand) IfCmp.getTarget(s).copy();
                    BranchProfileOperand prof = (BranchProfileOperand) IfCmp.getBranchProfile(s).copy();
                    if (cond.isEQUAL() || cond.isNOT_EQUAL()) {
                        if ((def.operator() == NEW || def.operator() == NEWARRAY) && c2.EQ(Address.zero())) {
                            // x = new ... ; y = x cmp null
                            return IfCmp.create(REF_IFCMP, y.copyRO(), AC(Address.zero()), AC(Address.zero()), cond.flipCode(), target, prof);
                        } else if (def.operator() == REF_ADD) {
                            Address c1 = getAddressValue(Binary.getVal2(def));
                            // x = a + c1; y = x cmp c2
                            return IfCmp.create(REF_IFCMP, y.copyRO(), a.copyRO(), AC(c2.toWord().minus(c1.toWord()).toAddress()), cond, target, prof);
                        } else if (def.operator() == REF_SUB) {
                            Address c1 = getAddressValue(Binary.getVal2(def));
                            // x = a - c1; y = x cmp c2
                            return IfCmp.create(REF_IFCMP, y.copyRO(), a.copyRO(), AC(c1.toWord().plus(c2.toWord()).toAddress()), cond, target, prof);
                        } else if (def.operator() == REF_NEG) {
                            // x = -a; y = x cmp c2
                            return IfCmp.create(REF_IFCMP, y.copyRO(), a.copyRO(), AC(Word.zero().minus(c2.toWord()).toAddress()), cond.flipOperands(), target, prof);
                        }
                    }
                }
                return null;
            }
        case INT_IFCMP2_opcode:
            {
                if (FOLD_INTS && FOLD_IFCMPS) {
                    int c2 = getIntValue(IfCmp2.getVal2(s));
                    ConditionOperand cond1 = (ConditionOperand) IfCmp2.getCond1(s).copy();
                    ConditionOperand cond2 = (ConditionOperand) IfCmp2.getCond2(s).copy();
                    BranchOperand target1 = (BranchOperand) IfCmp2.getTarget1(s).copy();
                    BranchOperand target2 = (BranchOperand) IfCmp2.getTarget2(s).copy();
                    BranchProfileOperand prof1 = (BranchProfileOperand) IfCmp2.getBranchProfile1(s).copy();
                    BranchProfileOperand prof2 = (BranchProfileOperand) IfCmp2.getBranchProfile2(s).copy();
                    if ((cond1.isEQUAL() || cond1.isNOT_EQUAL()) && (cond2.isEQUAL() || cond2.isNOT_EQUAL())) {
                        if (def.operator() == INT_ADD) {
                            int c1 = getIntValue(Binary.getVal2(def));
                            // x = a + c1; y = x cmp c2
                            return IfCmp2.create(INT_IFCMP2, y.copyRO(), a.copyRO(), IC(c2 - c1), cond1, target1, prof1, cond2, target2, prof2);
                        } else if (def.operator() == INT_SUB) {
                            int c1 = getIntValue(Binary.getVal2(def));
                            // x = a - c1; y = x cmp c2
                            return IfCmp2.create(INT_IFCMP2, y.copyRO(), a.copyRO(), IC(c1 + c2), cond1, target1, prof1, cond2, target2, prof2);
                        } else if (def.operator() == INT_NEG) {
                            // x = -a; y = x cmp c2
                            return IfCmp2.create(INT_IFCMP2, y.copyRO(), a.copyRO(), IC(-c2), cond1.flipOperands(), target1, prof1, cond2.flipOperands(), target2, prof2);
                        }
                    }
                }
                return null;
            }
        case INT_COND_MOVE_opcode:
        case LONG_COND_MOVE_opcode:
        case REF_COND_MOVE_opcode:
        case FLOAT_COND_MOVE_opcode:
        case DOUBLE_COND_MOVE_opcode:
        case GUARD_COND_MOVE_opcode:
            {
                if (FOLD_INTS && FOLD_CONDMOVES) {
                    Operand trueValue = CondMove.getTrueValue(s);
                    Operand falseValue = CondMove.getFalseValue(s);
                    ConditionOperand cond = (ConditionOperand) CondMove.getCond(s).copy();
                    boolean isEqualityTest = cond.isEQUAL() || cond.isNOT_EQUAL();
                    switch(def.getOpcode()) {
                        case INT_ADD_opcode:
                            if (isEqualityTest) {
                                int c1 = getIntValue(Binary.getVal2(def));
                                int c2 = getIntValue(CondMove.getVal2(s));
                                // x = a + c1; y = x cmp c2 ? trueValue : falseValue
                                return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), IC(c2 - c1), cond, trueValue, falseValue);
                            }
                            break;
                        case LONG_ADD_opcode:
                            if (isEqualityTest) {
                                long c1 = getLongValue(Binary.getVal2(def));
                                long c2 = getLongValue(CondMove.getVal2(s));
                                // x = a + c1; y = x cmp c2 ? trueValue : falseValue
                                return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c2 - c1), cond, trueValue, falseValue);
                            }
                            break;
                        case REF_ADD_opcode:
                            if (isEqualityTest) {
                                Address c1 = getAddressValue(Binary.getVal2(def));
                                Address c2 = getAddressValue(CondMove.getVal2(s));
                                // x = a + c1; y = x cmp c2 ? trueValue : falseValue
                                return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), AC(c2.toWord().minus(c1.toWord()).toAddress()), cond, trueValue, falseValue);
                            }
                            break;
                        case FLOAT_ADD_opcode:
                            {
                                float c1 = getFloatValue(Binary.getVal2(def));
                                float c2 = getFloatValue(CondMove.getVal2(s));
                                // x = a + c1; y = x cmp c2 ? trueValue : falseValue
                                return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), FC(c2 - c1), cond, trueValue, falseValue);
                            }
                        case DOUBLE_ADD_opcode:
                            {
                                double c1 = getDoubleValue(Binary.getVal2(def));
                                double c2 = getDoubleValue(CondMove.getVal2(s));
                                // x = a + c1; y = x cmp c2 ? trueValue : falseValue
                                return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), DC(c2 - c1), cond, trueValue, falseValue);
                            }
                        case INT_SUB_opcode:
                            if (isEqualityTest) {
                                int c1 = getIntValue(Binary.getVal2(def));
                                int c2 = getIntValue(CondMove.getVal2(s));
                                // x = a - c1; y = x cmp c2 ? trueValue : falseValue
                                return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), IC(c1 + c2), cond, trueValue, falseValue);
                            }
                            break;
                        case LONG_SUB_opcode:
                            if (isEqualityTest) {
                                long c1 = getLongValue(Binary.getVal2(def));
                                long c2 = getLongValue(CondMove.getVal2(s));
                                // x = a - c1; y = x cmp c2 ? trueValue : falseValue
                                return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c1 + c2), cond, trueValue, falseValue);
                            }
                            break;
                        case REF_SUB_opcode:
                            if (isEqualityTest) {
                                Address c1 = getAddressValue(Binary.getVal2(def));
                                Address c2 = getAddressValue(CondMove.getVal2(s));
                                // x = a - c1; y = x cmp c2 ? trueValue : falseValue
                                return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), AC(c1.toWord().plus(c2.toWord()).toAddress()), cond, trueValue, falseValue);
                            }
                            break;
                        case FLOAT_SUB_opcode:
                            {
                                float c1 = getFloatValue(Binary.getVal2(def));
                                float c2 = getFloatValue(CondMove.getVal2(s));
                                // x = a - c1; y = x cmp c2 ? trueValue : falseValue
                                return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), FC(c1 + c2), cond, trueValue, falseValue);
                            }
                        case DOUBLE_SUB_opcode:
                            {
                                double c1 = getDoubleValue(Binary.getVal2(def));
                                double c2 = getDoubleValue(CondMove.getVal2(s));
                                // x = a - c1; y = x cmp c2 ? trueValue : falseValue
                                return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), DC(c1 + c2), cond, trueValue, falseValue);
                            }
                        case INT_NEG_opcode:
                            if (isEqualityTest) {
                                int c2 = getIntValue(CondMove.getVal2(s));
                                // x = -a; y = x cmp c2 ? trueValue : falseValue
                                return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), IC(-c2), cond.flipOperands(), trueValue, falseValue);
                            }
                            break;
                        case LONG_NEG_opcode:
                            if (isEqualityTest) {
                                long c2 = getLongValue(CondMove.getVal2(s));
                                // x = -a; y = x cmp c2 ? trueValue : falseValue
                                return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(-c2), cond.flipOperands(), trueValue, falseValue);
                            }
                            break;
                        case REF_NEG_opcode:
                            if (isEqualityTest) {
                                Address c2 = getAddressValue(CondMove.getVal2(s));
                                // x = -a; y = x cmp c2 ? trueValue : falseValue
                                return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), AC(Word.zero().minus(c2.toWord()).toAddress()), cond.flipOperands(), trueValue, falseValue);
                            }
                            break;
                        case FLOAT_NEG_opcode:
                            {
                                float c2 = getFloatValue(CondMove.getVal2(s));
                                // x = -a; y = x cmp c2 ? trueValue : falseValue
                                return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), FC(-c2), cond.flipOperands(), trueValue, falseValue);
                            }
                        case DOUBLE_NEG_opcode:
                            {
                                double c2 = getDoubleValue(CondMove.getVal2(s));
                                // x = -a; y = x cmp c2 ? trueValue : falseValue
                                return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), DC(-c2), cond.flipOperands(), trueValue, falseValue);
                            }
                        case BOOLEAN_CMP_INT_opcode:
                            {
                                int c1 = getIntValue(BooleanCmp.getVal2(def));
                                int c2 = getIntValue(CondMove.getVal2(s));
                                // x = a cmp c1 ? true : false; y = x cmp c2 ? trueValue : falseValue
                                if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
                                    return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), IC(c1), BooleanCmp.getCond(def).copy().asCondition(), trueValue, falseValue);
                                } else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
                                    return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), IC(c1), BooleanCmp.getCond(def).copy().asCondition().flipCode(), trueValue, falseValue);
                                }
                                break;
                            }
                        case BOOLEAN_CMP_ADDR_opcode:
                            {
                                Address c1 = getAddressValue(BooleanCmp.getVal2(def));
                                int c2 = getIntValue(CondMove.getVal2(s));
                                // x = a cmp c1 ? true : false; y = x cmp c2 ? trueValue : falseValue
                                if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
                                    return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), AC(c1), BooleanCmp.getCond(def).copy().asCondition(), trueValue, falseValue);
                                } else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
                                    return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), AC(c1), BooleanCmp.getCond(def).flipCode(), trueValue, falseValue);
                                }
                                break;
                            }
                        case BOOLEAN_CMP_LONG_opcode:
                            {
                                long c1 = getLongValue(BooleanCmp.getVal2(def));
                                int c2 = getIntValue(CondMove.getVal2(s));
                                // x = a cmp c1 ? true : false; y = x cmp c2 ? trueValue : falseValue
                                if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
                                    return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c1), BooleanCmp.getCond(def).copy().asCondition(), trueValue, falseValue);
                                } else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
                                    return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c1), BooleanCmp.getCond(def).copy().asCondition().flipCode(), trueValue, falseValue);
                                } else {
                                    return null;
                                }
                            }
                        case BOOLEAN_CMP_DOUBLE_opcode:
                            {
                                double c1 = getDoubleValue(BooleanCmp.getVal2(def));
                                int c2 = getIntValue(CondMove.getVal2(s));
                                // x = a cmp c1 ? true : false; y = x cmp c2 ? trueValue : falseValue
                                if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
                                    return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), DC(c1), BooleanCmp.getCond(def).copy().asCondition(), trueValue, falseValue);
                                } else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
                                    return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), DC(c1), BooleanCmp.getCond(def).copy().asCondition().flipCode(), trueValue, falseValue);
                                }
                                break;
                            }
                        case BOOLEAN_CMP_FLOAT_opcode:
                            {
                                float c1 = getFloatValue(BooleanCmp.getVal2(def));
                                int c2 = getIntValue(CondMove.getVal2(s));
                                // x = a cmp c1 ? true : false; y = x cmp c2 ? trueValue : falseValue
                                if ((cond.isEQUAL() && c2 == 1) || (cond.isNOT_EQUAL() && c2 == 0)) {
                                    return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), FC(c1), BooleanCmp.getCond(def).copy().asCondition(), trueValue, falseValue);
                                } else if ((cond.isEQUAL() && c2 == 0) || (cond.isNOT_EQUAL() && c2 == 1)) {
                                    return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), FC(c1), BooleanCmp.getCond(def).copy().asCondition().flipCode(), trueValue, falseValue);
                                }
                                break;
                            }
                        case LONG_CMP_opcode:
                            {
                                long c1 = getLongValue(Binary.getVal2(def));
                                int c2 = getIntValue(CondMove.getVal2(s));
                                // x = a lcmp c1; y = y = x cmp c2 ? trueValue : falseValue
                                if (cond.isEQUAL() && c2 == 0) {
                                    return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.EQUAL(), trueValue, falseValue);
                                } else if (cond.isNOT_EQUAL() && c2 == 0) {
                                    return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.NOT_EQUAL(), trueValue, falseValue);
                                } else if ((cond.isEQUAL() && c2 == 1) || (cond.isGREATER() && c2 == 0)) {
                                    return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.GREATER(), trueValue, falseValue);
                                } else if (cond.isGREATER_EQUAL() && c2 == 0) {
                                    return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.GREATER_EQUAL(), trueValue, falseValue);
                                } else if ((cond.isEQUAL() && c2 == -1) || (cond.isLESS() && c2 == 0)) {
                                    return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.LESS(), trueValue, falseValue);
                                } else if (cond.isLESS_EQUAL() && c2 == 0) {
                                    return CondMove.create(s.operator(), y.copyRO(), a.copyRO(), LC(c1), ConditionOperand.LESS_EQUAL(), trueValue, falseValue);
                                }
                                break;
                            }
                        default:
                    }
                }
                return null;
            }
        case INT_NEG_opcode:
            {
                if (FOLD_INTS && FOLD_NEGS) {
                    if (def.operator() == INT_NEG) {
                        // x = -z; y = -x;
                        return Move.create(INT_MOVE, y.copyRO(), Unary.getVal(def).copy());
                    } else if (def.operator() == INT_MUL) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a * c1; y = -x;
                        return Binary.create(INT_MUL, y.copyRO(), a.copyRO(), IC(-c1));
                    } else if (def.operator() == INT_DIV) {
                        int c1 = getIntValue(GuardedBinary.getVal2(def));
                        Operand guard = GuardedBinary.getGuard(def);
                        // x = a / c1; y = -x;
                        return GuardedBinary.create(INT_DIV, y.copyRO(), a.copyRO(), IC(-c1), guard.copy());
                    } else if (FOLD_CONSTANTS_TO_LHS && (def.operator() == INT_ADD)) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a + c1; y = -x;
                        return Binary.create(INT_SUB, y.copyRO(), IC(-c1), a.copyRO());
                    } else if (FOLD_CONSTANTS_TO_LHS && (def.operator() == INT_SUB)) {
                        int c1 = getIntValue(Binary.getVal2(def));
                        // x = a - c1; y = -x;
                        return Binary.create(INT_SUB, y.copyRO(), IC(c1), a.copyRO());
                    }
                }
                return null;
            }
        case REF_NEG_opcode:
            {
                if (FOLD_REFS && FOLD_NEGS) {
                    if (def.operator() == REF_NEG) {
                        // x = -z; y = -x;
                        return Move.create(REF_MOVE, y.copyRO(), Unary.getVal(def).copy());
                    } else if (FOLD_CONSTANTS_TO_LHS && (def.operator() == REF_ADD)) {
                        Address c1 = getAddressValue(Binary.getVal2(def));
                        // x = a + c1; y = -x;
                        return Binary.create(REF_SUB, y.copyRO(), AC(Word.zero().minus(c1.toWord()).toAddress()), a.copyRO());
                    } else if (FOLD_CONSTANTS_TO_LHS && (def.operator() == REF_SUB)) {
                        Address c1 = getAddressValue(Binary.getVal2(def));
                        // x = a - c1; y = -x;
                        return Binary.create(REF_SUB, y.copyRO(), AC(c1), a.copyRO());
                    }
                }
                return null;
            }
        case LONG_NEG_opcode:
            {
                if (FOLD_LONGS && FOLD_NEGS) {
                    if (def.operator() == LONG_NEG) {
                        // x = -z; y = -x;
                        return Move.create(LONG_MOVE, y.copyRO(), Unary.getVal(def).copy());
                    } else if (def.operator() == LONG_MUL) {
                        long c1 = getLongValue(Binary.getVal2(def));
                        // x = a * c1; y = -x;
                        return Binary.create(LONG_MUL, y.copyRO(), a.copyRO(), LC(-c1));
                    } else if (def.operator() == LONG_DIV) {
                        long c1 = getLongValue(GuardedBinary.getVal2(def));
                        Operand guard = GuardedBinary.getGuard(def);
                        // x = a / c1; y = -x;
                        return GuardedBinary.create(LONG_DIV, y.copyRO(), a.copyRO(), LC(-c1), guard.copy());
                    } else if (FOLD_CONSTANTS_TO_LHS && (def.operator() == LONG_ADD)) {
                        long c1 = getLongValue(Binary.getVal2(def));
                        // x = a + c1; y = -x;
                        return Binary.create(LONG_SUB, y.copyRO(), LC(-c1), a.copyRO());
                    } else if (FOLD_CONSTANTS_TO_LHS && (def.operator() == LONG_SUB)) {
                        long c1 = getLongValue(Binary.getVal2(def));
                        // x = a - c1; y = -x;
                        return Binary.create(LONG_SUB, y.copyRO(), LC(c1), a.copyRO());
                    }
                }
                return null;
            }
        case FLOAT_NEG_opcode:
            {
                if (FOLD_FLOATS && FOLD_NEGS) {
                    if (def.operator() == FLOAT_NEG) {
                        // x = -z; y = -x;
                        return Move.create(FLOAT_MOVE, y.copyRO(), Unary.getVal(def).copy());
                    } else if (def.operator() == FLOAT_MUL) {
                        float c1 = getFloatValue(Binary.getVal2(def));
                        // x = a * c1; y = -x;
                        return Binary.create(FLOAT_MUL, y.copyRO(), a.copyRO(), FC(-c1));
                    } else if (def.operator() == FLOAT_DIV) {
                        float c1 = getFloatValue(Binary.getVal2(def));
                        // x = a / c1; y = -x;
                        return Binary.create(FLOAT_DIV, y.copyRO(), a.copyRO(), FC(-c1));
                    } else if (FOLD_CONSTANTS_TO_LHS && (def.operator() == FLOAT_ADD)) {
                        float c1 = getFloatValue(Binary.getVal2(def));
                        // x = a + c1; y = -x;
                        return Binary.create(FLOAT_SUB, y.copyRO(), FC(-c1), a.copyRO());
                    } else if (FOLD_CONSTANTS_TO_LHS && (def.operator() == FLOAT_SUB)) {
                        float c1 = getFloatValue(Binary.getVal2(def));
                        // x = a - c1; y = -x;
                        return Binary.create(FLOAT_SUB, y.copyRO(), FC(c1), a.copyRO());
                    }
                }
                return null;
            }
        case DOUBLE_NEG_opcode:
            {
                if (FOLD_DOUBLES && FOLD_NEGS) {
                    if (def.operator() == DOUBLE_NEG) {
                        // x = -z; y = -x;
                        return Move.create(DOUBLE_MOVE, y.copyRO(), Unary.getVal(def).copy());
                    } else if (def.operator() == DOUBLE_MUL) {
                        double c1 = getDoubleValue(Binary.getVal2(def));
                        // x = a * c1; y = -x;
                        return Binary.create(DOUBLE_MUL, y.copyRO(), a.copyRO(), DC(-c1));
                    } else if (def.operator() == DOUBLE_DIV) {
                        double c1 = getDoubleValue(Binary.getVal2(def));
                        // x = a / c1; y = -x;
                        return Binary.create(DOUBLE_DIV, y.copyRO(), a.copyRO(), DC(-c1));
                    } else if (FOLD_CONSTANTS_TO_LHS && (def.operator() == DOUBLE_ADD)) {
                        double c1 = getDoubleValue(Binary.getVal2(def));
                        // x = a + c1; y = -x;
                        return Binary.create(DOUBLE_SUB, y.copyRO(), DC(-c1), a.copyRO());
                    } else if (FOLD_CONSTANTS_TO_LHS && (def.operator() == DOUBLE_SUB)) {
                        double c1 = getDoubleValue(Binary.getVal2(def));
                        // x = a - c1; y = -x;
                        return Binary.create(DOUBLE_SUB, y.copyRO(), DC(c1), a.copyRO());
                    }
                }
                return null;
            }
        case BOOLEAN_NOT_opcode:
            {
                if (FOLD_INTS && FOLD_NOTS) {
                    if (def.operator() == BOOLEAN_NOT) {
                        // x = 1 ^ a; y = 1 ^ x;
                        return Move.create(INT_MOVE, y.copyRO(), Unary.getVal(def).copy());
                    } else if (BooleanCmp.conforms(def)) {
                        // x = a cmp b; y = !x
                        return BooleanCmp.create(def.operator(), y.copyRO(), BooleanCmp.getVal1(def).copy(), BooleanCmp.getVal2(def).copy(), ((ConditionOperand) BooleanCmp.getCond(def).copy()).flipCode(), ((BranchProfileOperand) BooleanCmp.getBranchProfile(def).copy()));
                    }
                }
                return null;
            }
        case INT_NOT_opcode:
            {
                if (FOLD_INTS && FOLD_NOTS) {
                    if (def.operator() == INT_NOT) {
                        // x = -1 ^ a; y = -1 ^ x;
                        return Move.create(INT_MOVE, y.copyRO(), a.copy());
                    }
                }
                return null;
            }
        case REF_NOT_opcode:
            {
                if (FOLD_REFS && FOLD_NOTS) {
                    if (def.operator() == REF_NOT) {
                        // x = -1 ^ a; y = -1 ^ x;
                        return Move.create(REF_MOVE, y.copyRO(), a.copy());
                    }
                }
                return null;
            }
        case LONG_NOT_opcode:
            {
                if (FOLD_LONGS && FOLD_NOTS) {
                    if (def.operator() == LONG_NOT) {
                        // x = -1 ^ a; y = -1 ^ x;
                        return Move.create(LONG_MOVE, y.copyRO(), a.copy());
                    }
                }
                return null;
            }
        case INT_2BYTE_opcode:
            {
                if (FOLD_INTS && FOLD_2CONVERSION) {
                    if ((def.operator() == INT_2BYTE) || (def.operator() == INT_2SHORT)) {
                        // x = (short)a; y = (byte)x;
                        return Unary.create(INT_2BYTE, y.copyRO(), a.copy());
                    } else if (def.operator() == INT_2USHORT) {
                        // x = (char)a; y = (byte)x;
                        return Binary.create(INT_AND, y.copyRO(), a.copy(), IC(0xFF));
                    }
                }
                return null;
            }
        case INT_2SHORT_opcode:
            {
                if (FOLD_INTS && FOLD_2CONVERSION) {
                    if (def.operator() == INT_2BYTE) {
                        // x = (byte)a; y = (short)x;
                        return Unary.create(INT_2BYTE, y.copyRO(), a.copy());
                    } else if (def.operator() == INT_2SHORT) {
                        // x = (short)a; y = (short)x;
                        return Unary.create(INT_2SHORT, y.copyRO(), a.copy());
                    } else if (def.operator() == INT_2USHORT) {
                        // x = (char)a; y = (short)x;
                        return Unary.create(INT_2USHORT, y.copyRO(), a.copy());
                    }
                }
                return null;
            }
        case INT_2USHORT_opcode:
            {
                if (FOLD_INTS && FOLD_2CONVERSION) {
                    if ((def.operator() == INT_2SHORT) || (def.operator() == INT_2USHORT)) {
                        // x = (short)a; y = (char)x;
                        return Unary.create(INT_2USHORT, y.copyRO(), a.copy());
                    }
                }
                return null;
            }
        case LONG_2INT_opcode:
            {
                if (FOLD_LONGS && FOLD_2CONVERSION) {
                    if (def.operator() == INT_2LONG) {
                        // x = (long)a; y = (int)x;
                        return Move.create(INT_MOVE, y.copyRO(), a.copy());
                    }
                }
                return null;
            }
        case INT_2LONG_opcode:
            // unused
            return null;
        case DOUBLE_2FLOAT_opcode:
            {
                if (FOLD_DOUBLES && FOLD_2CONVERSION) {
                    if (def.operator() == FLOAT_2DOUBLE) {
                        // x = (double)a; y = (float)x;
                        return Move.create(FLOAT_MOVE, y.copyRO(), a.copy());
                    }
                }
                return null;
            }
        case FLOAT_2DOUBLE_opcode:
            // unused
            return null;
        case INT_ZERO_CHECK_opcode:
            {
                if (FOLD_INTS && FOLD_CHECKS) {
                    if (def.operator() == INT_NEG) {
                        // x = -z; y = zerocheck x;
                        return ZeroCheck.create(INT_ZERO_CHECK, y.copyRO(), Unary.getVal(def).copy());
                    }
                }
                return null;
            }
        case LONG_ZERO_CHECK_opcode:
            {
                if (FOLD_INTS && FOLD_CHECKS) {
                    if (def.operator() == INT_NEG) {
                        // x = -z; y = zerocheck x;
                        return ZeroCheck.create(INT_ZERO_CHECK, y.copyRO(), Unary.getVal(def).copy());
                    }
                }
                return null;
            }
        case NEWARRAY_opcode:
            // unused
            return null;
        case BOUNDS_CHECK_opcode:
            {
                if (FOLD_CHECKS) {
                    if (def.operator() == NEWARRAY) {
                        // x = newarray xxx[c1]; y = boundscheck x, c2;
                        int c1 = getIntValue(NewArray.getSize(def));
                        int c2 = getIntValue(BoundsCheck.getIndex(s));
                        if (c2 >= 0 && c2 < c1) {
                            return Move.create(GUARD_MOVE, y.copyRO(), BoundsCheck.getGuard(def).copy());
                        }
                    }
                }
                return null;
            }
        case NULL_CHECK_opcode:
            {
                if (FOLD_CHECKS) {
                    if (def.operator() == NEWARRAY || def.operator() == NEW) {
                        // x = new xxx; y = nullcheck x;
                        return Move.create(GUARD_MOVE, y.copyRO(), new TrueGuardOperand());
                    }
                }
                return null;
            }
        case INSTANCEOF_opcode:
            {
                if (FOLD_CHECKS) {
                    TypeReference newType;
                    if (def.operator() == NEW) {
                        // x = new xxx; y = instanceof x, zzz;
                        newType = New.getType(def).getTypeRef();
                    } else if (def.operator() == NEWARRAY) {
                        // x = newarray xxx; y = instanceof x, zzz;
                        newType = NewArray.getType(def).getTypeRef();
                    } else {
                        return null;
                    }
                    TypeReference instanceofType = InstanceOf.getType(s).getTypeRef();
                    if (newType == instanceofType) {
                        return Move.create(INT_MOVE, y.copyRO(), IC(1));
                    } else {
                        return Move.create(INT_MOVE, y.copyRO(), IC(RuntimeEntrypoints.isAssignableWith(instanceofType.resolve(), newType.resolve()) ? 1 : 0));
                    }
                }
                return null;
            }
        case ARRAYLENGTH_opcode:
            {
                if (FOLD_CHECKS) {
                    if (def.operator() == NEWARRAY) {
                        // x = newarray xxx[c1]; y = arraylength x;
                        return Move.create(INT_MOVE, y.copyRO(), NewArray.getSize(def).copy());
                    }
                }
                return null;
            }
        default:
            OptimizingCompilerException.UNREACHABLE();
            return null;
    }
}
Also used : Address(org.vmmagic.unboxed.Address) NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) FloatConstantOperand(org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) LongConstantOperand(org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand) DoubleConstantOperand(org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) ObjectConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) TypeReference(org.jikesrvm.classloader.TypeReference) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand)

Example 14 with BranchOperand

use of org.jikesrvm.compilers.opt.ir.operand.BranchOperand in project JikesRVM by JikesRVM.

the class MinimalBURS method buildTree.

// //////////////////////////////
// Implementation
// //////////////////////////////
/**
 * Build a BURS Tree for each Instruction.
 * Complete BURS trees by adding leaf nodes as needed, and
 * creating tree edges by calling insertChild1() or insertChild2()
 * This step is also where we introduce intermediate tree nodes for
 * any LIR instruction that has &gt; 2 "real" operands e.g., a CALL.
 *
 * @param s The instruction for which a tree must be built
 * @return the root of the newly constructed tree
 */
private AbstractBURS_TreeNode buildTree(Instruction s) {
    AbstractBURS_TreeNode root = AbstractBURS_TreeNode.create(new DepGraphNode(s));
    AbstractBURS_TreeNode cur = root;
    for (Enumeration<Operand> uses = s.getUses(); uses.hasMoreElements(); ) {
        Operand op = uses.nextElement();
        if (op == null)
            continue;
        // Set child = AbstractBURS_TreeNode for operand op
        AbstractBURS_TreeNode child;
        if (op instanceof RegisterOperand) {
            if (op.asRegister().getRegister().isValidation())
                continue;
            child = Register;
        } else if (op instanceof IntConstantOperand) {
            child = new BURS_IntConstantTreeNode(((IntConstantOperand) op).value);
        } else if (op instanceof LongConstantOperand) {
            child = LongConstant;
        } else if (op instanceof AddressConstantOperand) {
            child = AddressConstant;
        } else if (op instanceof BranchOperand && s.isCall()) {
            child = BranchTarget;
        } else if (op instanceof InlinedOsrTypeInfoOperand && s.isYieldPoint()) {
            child = NullTreeNode;
        } else {
            continue;
        }
        // Attach child as child of cur_parent in correct position
        if (cur.child1 == null) {
            cur.child1 = child;
        } else if (cur.child2 == null) {
            cur.child2 = child;
        } else {
            // Create auxiliary node so as to represent
            // a instruction with arity > 2 in a binary tree.
            AbstractBURS_TreeNode child1 = cur.child2;
            AbstractBURS_TreeNode aux = AbstractBURS_TreeNode.create(OTHER_OPERAND_opcode);
            cur.child2 = aux;
            cur = aux;
            cur.child1 = child1;
            cur.child2 = child;
        }
    }
    // patch for calls & return
    switch(s.getOpcode()) {
        case CALL_opcode:
        case SYSCALL_opcode:
        case YIELDPOINT_OSR_opcode:
            if (cur.child2 == null) {
                cur.child2 = NullTreeNode;
            }
        // fall through
        case RETURN_opcode:
            if (cur.child1 == null) {
                cur.child1 = NullTreeNode;
            }
    }
    return root;
}
Also used : LongConstantOperand(org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) InlinedOsrTypeInfoOperand(org.jikesrvm.compilers.opt.ir.operand.InlinedOsrTypeInfoOperand) LongConstantOperand(org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) DepGraphNode(org.jikesrvm.compilers.opt.depgraph.DepGraphNode) InlinedOsrTypeInfoOperand(org.jikesrvm.compilers.opt.ir.operand.InlinedOsrTypeInfoOperand) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand)

Example 15 with BranchOperand

use of org.jikesrvm.compilers.opt.ir.operand.BranchOperand in project JikesRVM by JikesRVM.

the class BC2IR method _refIfNullHelper.

// helper function for ifnull/ifnonnull bytecodes
private Instruction _refIfNullHelper(ConditionOperand cond) {
    if (VM.VerifyAssertions)
        opt_assert(cond.isEQUAL() || cond.isNOT_EQUAL());
    int offset = bcodes.getBranchOffset();
    Operand op0 = popRef();
    if (offset == 3) {
        // remove frivolous REF_IFs
        return null;
    }
    if (CF_REFIF) {
        if (op0.isDefinitelyNull()) {
            if (cond.isEQUAL()) {
                if (DBG_CF) {
                    db(cond + ": changed branch to goto because predicate is true");
                }
                return _gotoHelper(offset);
            } else {
                if (DBG_CF) {
                    db(cond + ": eliminated branch because predicate is false");
                }
                return null;
            }
        }
        if (isNonNull(op0)) {
            if (cond.isNOT_EQUAL()) {
                if (DBG_CF) {
                    db(cond + ": changed branch to goto because predicate is true");
                }
                return _gotoHelper(offset);
            } else {
                if (DBG_CF) {
                    db(cond + ": eliminated branch because predicate is false");
                }
                return null;
            }
        }
    }
    RegisterOperand ref = (RegisterOperand) op0;
    BranchOperand branch = null;
    RegisterOperand guard = null;
    // Check for incorrect null checks on unboxed types
    if (ref.getType().isUnboxedType()) {
        throw new OptimizingCompilerException("Detected incorrect null check of unboxed type in " + gc.getMethod() + " at bytecode index " + instrIndex + " from class " + gc.getMethod().getDeclaringClass() + " . Use the methods provided on the unboxed types to do null checks!");
    }
    if (cond.isEQUAL()) {
        branch = generateTarget(offset);
        if (ref.getRegister().isLocal()) {
            int locNum = gc.getLocalNumberFor(ref.getRegister(), ref.getType());
            if (locNum != -1) {
                Operand loc = getLocal(locNum);
                if (loc instanceof RegisterOperand) {
                    RegisterOperand locr = (RegisterOperand) loc;
                    guard = gc.makeNullCheckGuard(locr.getRegister());
                    setGuardForRegOp(locr, guard.copyD2U());
                    setLocal(locNum, loc);
                }
            }
        }
    } else {
        boolean generated = false;
        if (ref.getRegister().isLocal()) {
            int locNum = gc.getLocalNumberFor(ref.getRegister(), ref.getType());
            if (locNum != -1) {
                Operand loc = getLocal(locNum);
                if (loc instanceof RegisterOperand) {
                    RegisterOperand locr = (RegisterOperand) loc;
                    RegisterOperand tlocr = locr.copyU2U();
                    guard = gc.makeNullCheckGuard(locr.getRegister());
                    setGuardForRegOp(tlocr, guard.copyD2U());
                    setLocal(locNum, tlocr);
                    branch = generateTarget(offset);
                    generated = true;
                    setLocal(locNum, locr);
                }
            }
        }
        if (!generated) {
            branch = generateTarget(offset);
        }
    }
    fallThrough = true;
    if (guard == null) {
        guard = gc.getTemps().makeTempValidation();
    }
    return IfCmp.create(REF_IFCMP, guard, ref, new NullConstantOperand(), cond, branch, gc.getConditionalBranchProfileOperand(instrIndex - bciAdjustment, offset < 0));
}
Also used : NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) LongConstantOperand(org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand) DoubleConstantOperand(org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand) TypeOperand(org.jikesrvm.compilers.opt.ir.operand.TypeOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) OsrTypeInfoOperand(org.jikesrvm.compilers.opt.ir.operand.OsrTypeInfoOperand) NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) FloatConstantOperand(org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) TrapCodeOperand(org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand) ConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ConstantOperand) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand) OsrPoint(org.jikesrvm.compilers.opt.ir.OsrPoint)

Aggregations

BranchOperand (org.jikesrvm.compilers.opt.ir.operand.BranchOperand)30 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)16 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)16 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)15 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)14 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)14 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)13 AddressConstantOperand (org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand)10 BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)9 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)8 LongConstantOperand (org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand)8 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)7 TrapCodeOperand (org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand)7 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)7 OptimizingCompilerException (org.jikesrvm.compilers.opt.OptimizingCompilerException)5 TypeOperand (org.jikesrvm.compilers.opt.ir.operand.TypeOperand)5 Operator (org.jikesrvm.compilers.opt.ir.Operator)4 OsrPoint (org.jikesrvm.compilers.opt.ir.OsrPoint)4 ConstantOperand (org.jikesrvm.compilers.opt.ir.operand.ConstantOperand)4 InlinedOsrTypeInfoOperand (org.jikesrvm.compilers.opt.ir.operand.InlinedOsrTypeInfoOperand)4