Search in sources :

Example 1 with IA32ConditionOperand

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

the class FinalMIRExpansion method expandYieldpoint.

private static void expandYieldpoint(Instruction s, IR ir, RVMMethod meth, IA32ConditionOperand ypCond) {
    // split the basic block after the yieldpoint, create a new
    // block at the end of the IR to hold the yieldpoint,
    // remove the yieldpoint (to prepare to out it in the new block at the end)
    BasicBlock thisBlock = s.getBasicBlock();
    BasicBlock nextBlock = thisBlock.splitNodeWithLinksAt(s, ir);
    BasicBlock yieldpoint = thisBlock.createSubBlock(s.getBytecodeIndex(), ir, 0);
    thisBlock.insertOut(yieldpoint);
    yieldpoint.insertOut(nextBlock);
    ir.cfg.addLastInCodeOrder(yieldpoint);
    s.remove();
    // change thread switch instruction into call to thread switch routine
    // NOTE: must make s the call instruction: it is the GC point!
    // must also inform the GCMap that s has been moved!!!
    Offset offset = meth.getOffset();
    LocationOperand loc = new LocationOperand(offset);
    Operand guard = TG();
    Operand target;
    if (JTOC_REGISTER == null) {
        target = MemoryOperand.D(Magic.getTocPointer().plus(offset), (byte) BYTES_IN_ADDRESS, loc, guard);
    } else {
        target = MemoryOperand.BD(ir.regpool.makeTocOp().asRegister(), offset, (byte) BYTES_IN_ADDRESS, loc, guard);
    }
    MIR_Call.mutate0(s, CALL_SAVE_VOLATILE, null, null, target, MethodOperand.STATIC(meth));
    yieldpoint.appendInstruction(s);
    ir.MIRInfo.gcIRMap.moveToEnd(s);
    yieldpoint.appendInstruction(MIR_Branch.create(IA32_JMP, nextBlock.makeJumpTarget()));
    // Check to see if threadSwitch requested
    Offset tsr = Entrypoints.takeYieldpointField.getOffset();
    MemoryOperand M = MemoryOperand.BD(ir.regpool.makeTROp(), tsr, (byte) 4, null, null);
    thisBlock.appendInstruction(MIR_Compare.create(IA32_CMP, M, IC(0)));
    thisBlock.appendInstruction(MIR_CondBranch.create(IA32_JCC, ypCond, yieldpoint.makeJumpTarget(), BranchProfileOperand.never()));
}
Also used : LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) IA32ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ia32.IA32ConditionOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) TrapCodeOperand(org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) MemoryOperand(org.jikesrvm.compilers.opt.ir.operand.MemoryOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) MemoryOperand(org.jikesrvm.compilers.opt.ir.operand.MemoryOperand) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) Offset(org.vmmagic.unboxed.Offset)

Example 2 with IA32ConditionOperand

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

the class FinalMIRExpansion method expand.

/**
 * @param ir the IR to expand
 * @return return value is garbage for IA32
 */
public static int expand(IR ir) {
    PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asIA32();
    MachineCodeOffsets mcOffsets = ir.MIRInfo.mcOffsets;
    for (Instruction next, p = ir.firstInstructionInCodeOrder(); p != null; p = next) {
        next = p.nextInstructionInCodeOrder();
        mcOffsets.setMachineCodeOffset(p, -1);
        switch(p.getOpcode()) {
            case IA32_MOVAPS_opcode:
                // a reg-reg move turned into a memory move where we can't guarantee alignment
                if (MIR_Move.getResult(p).isMemory() || MIR_Move.getValue(p).isMemory()) {
                    MIR_Move.mutate(p, IA32_MOVSS, MIR_Move.getClearResult(p), MIR_Move.getClearValue(p));
                }
                break;
            case IA32_MOVAPD_opcode:
                // a reg-reg move turned into a memory move where we can't guarantee alignment
                if (MIR_Move.getResult(p).isMemory() || MIR_Move.getValue(p).isMemory()) {
                    MIR_Move.mutate(p, IA32_MOVSD, MIR_Move.getClearResult(p), MIR_Move.getClearValue(p));
                }
                break;
            case IA32_TEST_opcode:
                // must be first; we can just commute it here.
                if (MIR_Test.getVal2(p).isMemory()) {
                    Operand tmp = MIR_Test.getClearVal1(p);
                    MIR_Test.setVal1(p, MIR_Test.getClearVal2(p));
                    MIR_Test.setVal2(p, tmp);
                }
                break;
            case NULL_CHECK_opcode:
                {
                    // mutate this into a TRAPIF, and then fall through to the the
                    // TRAP_IF case.
                    Operand ref = NullCheck.getRef(p);
                    MIR_TrapIf.mutate(p, IA32_TRAPIF, null, ref.copy(), IC(0), IA32ConditionOperand.EQ(), TrapCodeOperand.NullPtr());
                }
            // There is no break statement here on purpose!
            case IA32_TRAPIF_opcode:
                {
                    // split the basic block right before the IA32_TRAPIF
                    BasicBlock thisBlock = p.getBasicBlock();
                    BasicBlock trap = thisBlock.createSubBlock(p.getBytecodeIndex(), ir, 0f);
                    thisBlock.insertOut(trap);
                    BasicBlock nextBlock = thisBlock.splitNodeWithLinksAt(p, ir);
                    thisBlock.insertOut(trap);
                    TrapCodeOperand tc = MIR_TrapIf.getClearTrapCode(p);
                    p.remove();
                    mcOffsets.setMachineCodeOffset(nextBlock.firstInstruction(), -1);
                    // add code to thisBlock to conditionally jump to trap
                    Instruction cmp = MIR_Compare.create(IA32_CMP, MIR_TrapIf.getVal1(p).copy(), MIR_TrapIf.getVal2(p).copy());
                    if (p.isMarkedAsPEI()) {
                        // The trap if was explictly marked, which means that it has
                        // a memory operand into which we've folded a null check.
                        // Actually need a GC map for both the compare and the INT.
                        cmp.markAsPEI();
                        cmp.copyPosition(p);
                        ir.MIRInfo.gcIRMap.insertTwin(p, cmp);
                    }
                    thisBlock.appendInstruction(cmp);
                    thisBlock.appendInstruction(MIR_CondBranch.create(IA32_JCC, (IA32ConditionOperand) MIR_TrapIf.getCond(p).copy(), trap.makeJumpTarget(), null));
                    // add block at end to hold trap instruction, and
                    // insert trap sequence
                    ir.cfg.addLastInCodeOrder(trap);
                    if (tc.isArrayBounds()) {
                        // attempt to store index expression in processor object for
                        // C trap handler
                        Operand index = MIR_TrapIf.getVal2(p);
                        if (!(index instanceof RegisterOperand || index instanceof IntConstantOperand)) {
                            // index was spilled, and
                            index = IC(0xdeadbeef);
                        // we can't get it back here.
                        }
                        MemoryOperand mo = MemoryOperand.BD(ir.regpool.makeTROp(), ArchEntrypoints.arrayIndexTrapParamField.getOffset(), (byte) 4, null, null);
                        trap.appendInstruction(MIR_Move.create(IA32_MOV, mo, index.copy()));
                    }
                    // NOTE: must make p the trap instruction: it is the GC point!
                    // IMPORTANT: must also inform the GCMap that the instruction has
                    // been moved!!!
                    trap.appendInstruction(MIR_Trap.mutate(p, IA32_INT, null, tc));
                    ir.MIRInfo.gcIRMap.moveToEnd(p);
                    if (tc.isStackOverflow()) {
                        // only stackoverflow traps resume at next instruction.
                        trap.appendInstruction(MIR_Branch.create(IA32_JMP, nextBlock.makeJumpTarget()));
                    }
                }
                break;
            case IA32_FMOV_ENDING_LIVE_RANGE_opcode:
                {
                    Operand result = MIR_Move.getResult(p);
                    Operand value = MIR_Move.getValue(p);
                    if (result.isRegister() && value.isRegister()) {
                        if (result.similar(value)) {
                            // eliminate useless move
                            p.remove();
                        } else {
                            int i = PhysicalRegisterSet.getFPRIndex(result.asRegister().getRegister());
                            int j = PhysicalRegisterSet.getFPRIndex(value.asRegister().getRegister());
                            if (i == 0) {
                                MIR_XChng.mutate(p, IA32_FXCH, result, value);
                            } else if (j == 0) {
                                MIR_XChng.mutate(p, IA32_FXCH, value, result);
                            } else {
                                expandFmov(p, phys);
                            }
                        }
                    } else {
                        expandFmov(p, phys);
                    }
                    break;
                }
            case DUMMY_DEF_opcode:
            case DUMMY_USE_opcode:
            case REQUIRE_ESP_opcode:
            case ADVISE_ESP_opcode:
                p.remove();
                break;
            case IA32_FMOV_opcode:
                expandFmov(p, phys);
                break;
            case IA32_MOV_opcode:
                // Convert 0L to 0 to allow optimization into XOR.
                if (MIR_Move.getResult(p).isRegister() && MIR_Move.getValue(p).isLongConstant() && MIR_Move.getValue(p).asLongConstant().value == 0L) {
                    MIR_Move.setValue(p, IC(0));
                }
                // Replace result = IA32_MOV 0 with result = IA32_XOR result, result
                if (MIR_Move.getResult(p).isRegister() && MIR_Move.getValue(p).isIntConstant() && MIR_Move.getValue(p).asIntConstant().value == 0) {
                    // Calculate what flags are defined in coming instructions before a use of a flag or BBend
                    Instruction x = next;
                    int futureDefs = 0;
                    while (!BBend.conforms(x) && !PhysicalDefUse.usesEFLAGS(x.operator())) {
                        futureDefs |= x.operator().implicitDefs;
                        x = x.nextInstructionInCodeOrder();
                    }
                    // If the flags will be destroyed prior to use or we reached the end of the basic block
                    if (BBend.conforms(x) || (futureDefs & PhysicalDefUse.maskAF_CF_OF_PF_SF_ZF) == PhysicalDefUse.maskAF_CF_OF_PF_SF_ZF) {
                        Operand result = MIR_Move.getClearResult(p);
                        MIR_BinaryAcc.mutate(p, IA32_XOR, result, result.copy());
                    }
                }
                break;
            case IA32_SET__B_opcode:
                // Replace <cmp>, set__b, movzx__b with xor, <cmp>, set__b
                if (MIR_Set.getResult(p).isRegister() && MIR_Unary.conforms(next) && (next.operator() == IA32_MOVZX__B) && MIR_Unary.getResult(next).isRegister() && MIR_Unary.getVal(next).similar(MIR_Unary.getResult(next)) && MIR_Unary.getVal(next).similar(MIR_Set.getResult(p))) {
                    // Find instruction in this basic block that defines flags
                    Instruction x = p.prevInstructionInCodeOrder();
                    Operand result = MIR_Unary.getResult(next);
                    boolean foundCmp = false;
                    outer: while (!Label.conforms(x)) {
                        Enumeration<Operand> e = x.getUses();
                        while (e.hasMoreElements()) {
                            // used by the <cmp> or intervening instruction
                            if (e.nextElement().similar(result)) {
                                break outer;
                            }
                        }
                        if (PhysicalDefUse.definesEFLAGS(x.operator()) && !PhysicalDefUse.usesEFLAGS(x.operator())) {
                            // we found a <cmp> that doesn't use the result or the flags
                            // that would be clobbered by the xor
                            foundCmp = true;
                            break outer;
                        }
                        x = x.prevInstructionInCodeOrder();
                    }
                    if (foundCmp) {
                        // We found the <cmp>, mutate the movzx__b into an xor and insert it before the <cmp>
                        next.remove();
                        MIR_BinaryAcc.mutate(next, IA32_XOR, result, MIR_Unary.getVal(next));
                        x.insertBefore(next);
                        // get ready for the next instruction
                        next = p.nextInstructionInCodeOrder();
                    }
                }
                break;
            case IA32_LEA_opcode:
                {
                    // Sometimes we're over eager in BURS in using LEAs and after register
                    // allocation we can simplify to the accumulate form
                    // replace reg1 = LEA [reg1 + reg2] with reg1 = reg1 + reg2
                    // replace reg1 = LEA [reg1 + c1] with reg1 = reg1 + c1
                    // replace reg1 = LEA [reg1 << c1] with reg1 = reg1 << c1
                    MemoryOperand value = MIR_Lea.getValue(p);
                    RegisterOperand result = MIR_Lea.getResult(p);
                    if ((value.base != null && value.base.getRegister() == result.getRegister()) || (value.index != null && value.index.getRegister() == result.getRegister())) {
                        // Calculate what flags are defined in coming instructions before a use of a flag or BBend
                        Instruction x = next;
                        int futureDefs = 0;
                        while (!BBend.conforms(x) && !PhysicalDefUse.usesEFLAGS(x.operator())) {
                            futureDefs |= x.operator().implicitDefs;
                            x = x.nextInstructionInCodeOrder();
                        }
                        // If the flags will be destroyed prior to use or we reached the end of the basic block
                        if (BBend.conforms(x) || (futureDefs & PhysicalDefUse.maskAF_CF_OF_PF_SF_ZF) == PhysicalDefUse.maskAF_CF_OF_PF_SF_ZF) {
                            if (value.base != null && value.index != null && value.index.getRegister() == result.getRegister() && value.disp.isZero() && value.scale == 0) {
                                // reg1 = lea [base + reg1] -> add reg1, base
                                MIR_BinaryAcc.mutate(p, IA32_ADD, result, value.base);
                            } else if (value.base != null && value.base.getRegister() == result.getRegister() && value.index != null && value.disp.isZero() && value.scale == 0) {
                                // reg1 = lea [reg1 + index] -> add reg1, index
                                MIR_BinaryAcc.mutate(p, IA32_ADD, result, value.index);
                            } else if (value.base != null && value.base.getRegister() == result.getRegister() && value.index == null) {
                                if (VM.VerifyAssertions)
                                    VM._assert(fits(value.disp, 32));
                                // reg1 = lea [reg1 + disp] -> add reg1, disp
                                MIR_BinaryAcc.mutate(p, IA32_ADD, result, IC(value.disp.toInt()));
                            } else if (value.base == null && value.index != null && value.index.getRegister() == result.getRegister() && value.scale == 0) {
                                if (VM.VerifyAssertions)
                                    VM._assert(fits(value.disp, 32));
                                // reg1 = lea [reg1 + disp] -> add reg1, disp
                                MIR_BinaryAcc.mutate(p, IA32_ADD, result, IC(value.disp.toInt()));
                            } else if (value.base == null && value.index != null && value.index.getRegister() == result.getRegister() && value.disp.isZero()) {
                                // reg1 = lea [reg1 << scale] -> shl reg1, scale
                                if (value.scale == 0) {
                                    p.remove();
                                } else if (value.scale == 1) {
                                    MIR_BinaryAcc.mutate(p, IA32_ADD, result, value.index);
                                } else {
                                    MIR_BinaryAcc.mutate(p, IA32_SHL, result, IC(value.scale));
                                }
                            }
                        }
                    }
                }
                break;
            case IA32_FCLEAR_opcode:
                expandFClear(p, ir);
                break;
            case IA32_JCC2_opcode:
                p.insertBefore(MIR_CondBranch.create(IA32_JCC, MIR_CondBranch2.getClearCond1(p), MIR_CondBranch2.getClearTarget1(p), MIR_CondBranch2.getClearBranchProfile1(p)));
                MIR_CondBranch.mutate(p, IA32_JCC, MIR_CondBranch2.getClearCond2(p), MIR_CondBranch2.getClearTarget2(p), MIR_CondBranch2.getClearBranchProfile2(p));
                break;
            case CALL_SAVE_VOLATILE_opcode:
                p.changeOperatorTo(IA32_CALL);
                break;
            case IA32_LOCK_CMPXCHG_opcode:
                p.insertBefore(MIR_Empty.create(IA32_LOCK));
                p.changeOperatorTo(IA32_CMPXCHG);
                break;
            case IA32_LOCK_CMPXCHG8B_opcode:
                p.insertBefore(MIR_Empty.create(IA32_LOCK));
                p.changeOperatorTo(IA32_CMPXCHG8B);
                break;
            case YIELDPOINT_PROLOGUE_opcode:
                expandYieldpoint(p, ir, Entrypoints.optThreadSwitchFromPrologueMethod, IA32ConditionOperand.NE());
                break;
            case YIELDPOINT_EPILOGUE_opcode:
                expandYieldpoint(p, ir, Entrypoints.optThreadSwitchFromEpilogueMethod, IA32ConditionOperand.NE());
                break;
            case YIELDPOINT_BACKEDGE_opcode:
                expandYieldpoint(p, ir, Entrypoints.optThreadSwitchFromBackedgeMethod, IA32ConditionOperand.GT());
                break;
            case YIELDPOINT_OSR_opcode:
                // must yield, does not check threadSwitch request
                expandUnconditionalYieldpoint(p, ir, Entrypoints.optThreadSwitchFromOsrOptMethod);
                break;
        }
    }
    return 0;
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) Enumeration(java.util.Enumeration) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) IA32ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ia32.IA32ConditionOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) TrapCodeOperand(org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) MemoryOperand(org.jikesrvm.compilers.opt.ir.operand.MemoryOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) MemoryOperand(org.jikesrvm.compilers.opt.ir.operand.MemoryOperand) PhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.ia32.PhysicalRegisterSet) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) MachineCodeOffsets(org.jikesrvm.compilers.opt.mir2mc.MachineCodeOffsets) TrapCodeOperand(org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Example 3 with IA32ConditionOperand

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

the class ComplexLIR2MIRExpansion method basic_long_ifcmp.

private static void basic_long_ifcmp(Instruction s, IR ir, ConditionOperand cond, Register xh, Register xl, Operand yh, Operand yl) {
    if (cond.isEQUAL() || cond.isNOT_EQUAL()) {
        RegisterOperand th = ir.regpool.makeTempInt();
        RegisterOperand tl = ir.regpool.makeTempInt();
        // tricky... ((xh^yh)|(xl^yl) == 0) <==> (lhll == rhrl)!!
        s.insertBefore(MIR_Move.create(IA32_MOV, th, new RegisterOperand(xh, TypeReference.Int)));
        s.insertBefore(MIR_BinaryAcc.create(IA32_XOR, th.copyD2D(), yh));
        s.insertBefore(MIR_Move.create(IA32_MOV, tl, new RegisterOperand(xl, TypeReference.Int)));
        s.insertBefore(MIR_BinaryAcc.create(IA32_XOR, tl.copyD2D(), yl));
        s.insertBefore(MIR_BinaryAcc.create(IA32_OR, th.copyD2D(), tl.copyD2U()));
        MIR_CondBranch.mutate(s, IA32_JCC, new IA32ConditionOperand(cond), IfCmp.getTarget(s), IfCmp.getBranchProfile(s));
    } else {
        // Do the naive thing and generate multiple compare/branch implementation.
        IA32ConditionOperand cond1;
        IA32ConditionOperand cond2;
        IA32ConditionOperand cond3;
        if (cond.isLESS()) {
            cond1 = IA32ConditionOperand.LT();
            cond2 = IA32ConditionOperand.GT();
            cond3 = IA32ConditionOperand.LLT();
        } else if (cond.isGREATER()) {
            cond1 = IA32ConditionOperand.GT();
            cond2 = IA32ConditionOperand.LT();
            cond3 = IA32ConditionOperand.LGT();
        } else if (cond.isLESS_EQUAL()) {
            cond1 = IA32ConditionOperand.LT();
            cond2 = IA32ConditionOperand.GT();
            cond3 = IA32ConditionOperand.LLE();
        } else if (cond.isGREATER_EQUAL()) {
            cond1 = IA32ConditionOperand.GT();
            cond2 = IA32ConditionOperand.LT();
            cond3 = IA32ConditionOperand.LGE();
        } else {
            // I don't think we use the unsigned compares for longs,
            // so defer actually implementing them until we find a test case. --dave
            cond1 = cond2 = cond3 = null;
            OptimizingCompilerException.TODO();
        }
        BasicBlock myBlock = s.getBasicBlock();
        BasicBlock test2Block = myBlock.createSubBlock(s.getBytecodeIndex(), ir, 0.25f);
        BasicBlock falseBlock = myBlock.splitNodeAt(s, ir);
        BasicBlock trueBlock = IfCmp.getTarget(s).target.getBasicBlock();
        falseBlock.recomputeNormalOut(ir);
        myBlock.insertOut(test2Block);
        myBlock.insertOut(falseBlock);
        myBlock.insertOut(trueBlock);
        test2Block.insertOut(falseBlock);
        test2Block.insertOut(trueBlock);
        ir.cfg.linkInCodeOrder(myBlock, test2Block);
        ir.cfg.linkInCodeOrder(test2Block, falseBlock);
        s.remove();
        myBlock.appendInstruction(CPOS(s, MIR_Compare.create(IA32_CMP, new RegisterOperand(xh, TypeReference.Int), yh)));
        myBlock.appendInstruction(CPOS(s, MIR_CondBranch2.create(IA32_JCC2, cond1, trueBlock.makeJumpTarget(), new BranchProfileOperand(), cond2, falseBlock.makeJumpTarget(), new BranchProfileOperand())));
        test2Block.appendInstruction(CPOS(s, MIR_Compare.create(IA32_CMP, new RegisterOperand(xl, TypeReference.Int), yl)));
        test2Block.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, cond3, trueBlock.makeJumpTarget(), new BranchProfileOperand())));
    }
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) IA32ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ia32.IA32ConditionOperand)

Example 4 with IA32ConditionOperand

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

the class ComplexLIR2MIRExpansion method long_ifcmp_imm.

private static Instruction long_ifcmp_imm(Instruction s, IR ir) {
    Instruction nextInstr = s.nextInstructionInCodeOrder();
    ConditionOperand cond = IfCmp.getCond(s);
    Register xh = ((RegisterOperand) IfCmp.getVal1(s)).getRegister();
    Register xl = ir.regpool.getSecondReg(xh);
    LongConstantOperand rhs = (LongConstantOperand) IfCmp.getVal2(s);
    int low = rhs.lower32();
    int high = rhs.upper32();
    IntConstantOperand yh = IC(high);
    IntConstantOperand yl = IC(low);
    if (cond.isEQUAL() || cond.isNOT_EQUAL()) {
        // tricky... ((xh^yh)|(xl^yl) == 0) <==> (lhll == rhrl)!!
        Register th = ir.regpool.getInteger();
        Register tl = ir.regpool.getInteger();
        if (high == 0) {
            if (low == 0) {
                // 0,0
                s.insertBefore(MIR_Move.create(IA32_MOV, new RegisterOperand(th, TypeReference.Int), new RegisterOperand(xh, TypeReference.Int)));
                s.insertBefore(MIR_BinaryAcc.create(IA32_OR, new RegisterOperand(th, TypeReference.Int), new RegisterOperand(xl, TypeReference.Int)));
            } else if (low == -1) {
                // 0,-1
                s.insertBefore(MIR_Move.create(IA32_MOV, new RegisterOperand(tl, TypeReference.Int), new RegisterOperand(xl, TypeReference.Int)));
                s.insertBefore(MIR_UnaryAcc.create(IA32_NOT, new RegisterOperand(tl, TypeReference.Int)));
                s.insertBefore(MIR_BinaryAcc.create(IA32_OR, new RegisterOperand(tl, TypeReference.Int), new RegisterOperand(xh, TypeReference.Int)));
            } else {
                // 0,*
                s.insertBefore(MIR_Move.create(IA32_MOV, new RegisterOperand(tl, TypeReference.Int), new RegisterOperand(xl, TypeReference.Int)));
                s.insertBefore(MIR_BinaryAcc.create(IA32_XOR, new RegisterOperand(tl, TypeReference.Int), yl));
                s.insertBefore(MIR_BinaryAcc.create(IA32_OR, new RegisterOperand(tl, TypeReference.Int), new RegisterOperand(xh, TypeReference.Int)));
            }
        } else if (high == -1) {
            if (low == 0) {
                // -1,0
                s.insertBefore(MIR_Move.create(IA32_MOV, new RegisterOperand(th, TypeReference.Int), new RegisterOperand(xh, TypeReference.Int)));
                s.insertBefore(MIR_UnaryAcc.create(IA32_NOT, new RegisterOperand(th, TypeReference.Int)));
                s.insertBefore(MIR_BinaryAcc.create(IA32_OR, new RegisterOperand(th, TypeReference.Int), new RegisterOperand(xl, TypeReference.Int)));
            } else if (low == -1) {
                // -1,-1
                s.insertBefore(MIR_Move.create(IA32_MOV, new RegisterOperand(th, TypeReference.Int), new RegisterOperand(xh, TypeReference.Int)));
                s.insertBefore(MIR_UnaryAcc.create(IA32_NOT, new RegisterOperand(th, TypeReference.Int)));
                s.insertBefore(MIR_Move.create(IA32_MOV, new RegisterOperand(tl, TypeReference.Int), new RegisterOperand(xl, TypeReference.Int)));
                s.insertBefore(MIR_UnaryAcc.create(IA32_NOT, new RegisterOperand(tl, TypeReference.Int)));
                s.insertBefore(MIR_BinaryAcc.create(IA32_OR, new RegisterOperand(th, TypeReference.Int), new RegisterOperand(tl, TypeReference.Int)));
            } else {
                // -1,*
                s.insertBefore(MIR_Move.create(IA32_MOV, new RegisterOperand(th, TypeReference.Int), new RegisterOperand(xh, TypeReference.Int)));
                s.insertBefore(MIR_UnaryAcc.create(IA32_NOT, new RegisterOperand(th, TypeReference.Int)));
                s.insertBefore(MIR_Move.create(IA32_MOV, new RegisterOperand(tl, TypeReference.Int), new RegisterOperand(xl, TypeReference.Int)));
                s.insertBefore(MIR_BinaryAcc.create(IA32_XOR, new RegisterOperand(tl, TypeReference.Int), yl));
                s.insertBefore(MIR_BinaryAcc.create(IA32_OR, new RegisterOperand(th, TypeReference.Int), new RegisterOperand(tl, TypeReference.Int)));
            }
        } else {
            if (low == 0) {
                // *,0
                s.insertBefore(MIR_Move.create(IA32_MOV, new RegisterOperand(th, TypeReference.Int), new RegisterOperand(xh, TypeReference.Int)));
                s.insertBefore(MIR_BinaryAcc.create(IA32_XOR, new RegisterOperand(th, TypeReference.Int), yh));
                s.insertBefore(MIR_BinaryAcc.create(IA32_OR, new RegisterOperand(th, TypeReference.Int), new RegisterOperand(xl, TypeReference.Int)));
            } else if (low == -1) {
                // *,-1
                s.insertBefore(MIR_Move.create(IA32_MOV, new RegisterOperand(th, TypeReference.Int), new RegisterOperand(xh, TypeReference.Int)));
                s.insertBefore(MIR_BinaryAcc.create(IA32_XOR, new RegisterOperand(th, TypeReference.Int), yh));
                s.insertBefore(MIR_Move.create(IA32_MOV, new RegisterOperand(tl, TypeReference.Int), new RegisterOperand(xl, TypeReference.Int)));
                s.insertBefore(MIR_UnaryAcc.create(IA32_NOT, new RegisterOperand(tl, TypeReference.Int)));
                s.insertBefore(MIR_BinaryAcc.create(IA32_OR, new RegisterOperand(th, TypeReference.Int), new RegisterOperand(tl, TypeReference.Int)));
            } else {
                // neither high nor low is special
                s.insertBefore(MIR_Move.create(IA32_MOV, new RegisterOperand(th, TypeReference.Int), new RegisterOperand(xh, TypeReference.Int)));
                s.insertBefore(MIR_BinaryAcc.create(IA32_XOR, new RegisterOperand(th, TypeReference.Int), yh));
                s.insertBefore(MIR_Move.create(IA32_MOV, new RegisterOperand(tl, TypeReference.Int), new RegisterOperand(xl, TypeReference.Int)));
                s.insertBefore(MIR_BinaryAcc.create(IA32_XOR, new RegisterOperand(tl, TypeReference.Int), yl));
                s.insertBefore(MIR_BinaryAcc.create(IA32_OR, new RegisterOperand(th, TypeReference.Int), new RegisterOperand(tl, TypeReference.Int)));
            }
        }
        MIR_CondBranch.mutate(s, IA32_JCC, new IA32ConditionOperand(cond), IfCmp.getTarget(s), IfCmp.getBranchProfile(s));
        return nextInstr;
    } else {
        // pick up a few special cases where the sign of xh is sufficient
        if (rhs.value == 0L) {
            if (cond.isLESS()) {
                // xh < 0 implies true
                s.insertBefore(MIR_Compare.create(IA32_CMP, new RegisterOperand(xh, TypeReference.Int), IC(0)));
                MIR_CondBranch.mutate(s, IA32_JCC, IA32ConditionOperand.LT(), IfCmp.getTarget(s), IfCmp.getBranchProfile(s));
                return nextInstr;
            } else if (cond.isGREATER_EQUAL()) {
                s.insertBefore(MIR_Compare.create(IA32_CMP, new RegisterOperand(xh, TypeReference.Int), IC(0)));
                MIR_CondBranch.mutate(s, IA32_JCC, IA32ConditionOperand.GE(), IfCmp.getTarget(s), IfCmp.getBranchProfile(s));
                return nextInstr;
            }
        } else if (rhs.value == -1L) {
            if (cond.isLESS_EQUAL()) {
                s.insertBefore(MIR_Compare.create(IA32_CMP, new RegisterOperand(xh, TypeReference.Int), IC(-1)));
                MIR_CondBranch.mutate(s, IA32_JCC, IA32ConditionOperand.LE(), IfCmp.getTarget(s), IfCmp.getBranchProfile(s));
                return nextInstr;
            } else if (cond.isGREATER()) {
                s.insertBefore(MIR_Compare.create(IA32_CMP, new RegisterOperand(xh, TypeReference.Int), IC(0)));
                MIR_CondBranch.mutate(s, IA32_JCC, IA32ConditionOperand.GE(), IfCmp.getTarget(s), IfCmp.getBranchProfile(s));
                return nextInstr;
            }
        }
        basic_long_ifcmp(s, ir, cond, xh, xl, yh, yl);
        return nextInstr;
    }
}
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) Register(org.jikesrvm.compilers.opt.ir.Register) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) IA32ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ia32.IA32ConditionOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) IA32ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ia32.IA32ConditionOperand)

Aggregations

RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)4 IA32ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ia32.IA32ConditionOperand)4 BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)3 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)3 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)3 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)2 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)2 MemoryOperand (org.jikesrvm.compilers.opt.ir.operand.MemoryOperand)2 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)2 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)2 TrapCodeOperand (org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand)2 Enumeration (java.util.Enumeration)1 Register (org.jikesrvm.compilers.opt.ir.Register)1 PhysicalRegisterSet (org.jikesrvm.compilers.opt.ir.ia32.PhysicalRegisterSet)1 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)1 LongConstantOperand (org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand)1 MachineCodeOffsets (org.jikesrvm.compilers.opt.mir2mc.MachineCodeOffsets)1 Offset (org.vmmagic.unboxed.Offset)1