Search in sources :

Example 96 with BasicBlock

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

the class LocalCastOptimization method perform.

/**
 * Main routine: perform the transformation.
 * @param ir the IR to transform
 */
@Override
public void perform(IR ir) {
    // loop over all basic blocks ...
    for (Enumeration<BasicBlock> e = ir.getBasicBlocks(); e.hasMoreElements(); ) {
        BasicBlock bb = e.nextElement();
        if (bb.isEmpty())
            continue;
        container.counter2++;
        if (bb.getInfrequent()) {
            container.counter1++;
            if (ir.options.FREQ_FOCUS_EFFORT)
                continue;
        }
        // visit each instruction in the basic block
        for (Enumeration<Instruction> ie = bb.forwardInstrEnumerator(); ie.hasMoreElements(); ) {
            Instruction s = ie.nextElement();
            if (TypeCheck.conforms(s) && (invertNullAndTypeChecks(s) || pushTypeCheckBelowIf(s, ir))) {
                // hack: we may have modified the instructions; start over
                ie = bb.forwardInstrEnumerator();
            }
        }
    }
}
Also used : BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Example 97 with BasicBlock

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

the class LocalCastOptimization method pushTypeCheckBelowIf.

/**
 * Where legal, move a type check below an if instruction.
 * @param s the potential typecheck instruction
 * @param ir the governing IR
 * @return {@code true} if and only if a type check was moved
 */
private boolean pushTypeCheckBelowIf(Instruction s, IR ir) {
    if (s.operator() == CHECKCAST) {
        Register r = TypeCheck.getRef(s).asRegister().getRegister();
        Instruction n = s.nextInstructionInCodeOrder();
        /* find moves of the checked value, so that we can also
         optimize cases where the checked value is moved before
         it is used
      */
        while (n.operator() == REF_MOVE && Move.getVal(n) instanceof RegisterOperand && Move.getVal(n).asRegister().getRegister() == r) {
            r = Move.getResult(n).asRegister().getRegister();
            n = n.nextInstructionInCodeOrder();
        }
        if (n.operator() == REF_IFCMP && IfCmp.getVal2(n) instanceof NullConstantOperand && IfCmp.getVal1(n) instanceof RegisterOperand && r == IfCmp.getVal1(n).asRegister().getRegister()) {
            BasicBlock newBlock, patchBlock;
            BasicBlock myBlock = n.getBasicBlock();
            Instruction after = n.nextInstructionInCodeOrder();
            if (IfCmp.getCond(n).isEQUAL()) /*  We fall through on non-NULL values, so the
              checkcast must be on the not-taken path
              from the branch.  There are 3 cases:
              1. n is the last instruction in its basic block,
              in which case control falls through to the next
              block in code order.  This case is if the
              instruction after n is a BBEND
          */
            {
                if (after.operator() == BBEND) {
                    patchBlock = myBlock.nextBasicBlockInCodeOrder();
                } else if (after.operator() == GOTO) {
                    /* 2. n is followed by an unconditional goto.  In
               this case control jumps to the target of the
               goto.
            */
                    patchBlock = after.getBranchTarget();
                } else if (after.operator() == REF_IFCMP) {
                    /* 3. n is followed by another conditional branch. In
               this case, we will split the basic block to make
               n the last instruction in the block, and then
               we have the fall through case again.
            */
                    patchBlock = myBlock.splitNodeAt(n, ir);
                    myBlock.insertOut(patchBlock);
                    ir.cfg.linkInCodeOrder(myBlock, patchBlock);
                } else {
                    /* this is a bad thing */
                    return false;
                }
            } else /* We branch on not-NULL values, so the checkcast
             must be spliced in before the branch target
          */
            {
                patchBlock = n.getBranchTarget();
            }
            /* add block between branch and appropriate successor */
            newBlock = IRTools.makeBlockOnEdge(myBlock, patchBlock, ir);
            /* put check in new block */
            s.remove();
            TypeCheck.mutate(s, CHECKCAST_NOTNULL, TypeCheck.getClearResult(s), TypeCheck.getClearRef(s), TypeCheck.getClearType(s), IfCmp.getGuardResult(n).copyRO());
            newBlock.prependInstruction(s);
            return true;
        }
    }
    return false;
}
Also used : NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Register(org.jikesrvm.compilers.opt.ir.Register) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Example 98 with BasicBlock

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

the class LocalCopyProp method perform.

/**
 * Perform local constant propagation for a method.
 *
 * @param ir the IR to optimize
 */
@Override
public void perform(IR ir) {
    HashMap<Register, Operand> info = new HashMap<Register, Operand>();
    for (BasicBlock bb = ir.firstBasicBlockInCodeOrder(); bb != null; bb = bb.nextBasicBlockInCodeOrder()) {
        if (bb.isEmpty())
            continue;
        container.counter2++;
        if (bb.getInfrequent()) {
            container.counter1++;
            if (ir.options.FREQ_FOCUS_EFFORT)
                continue;
        }
        // iterate over all instructions in the basic block
        for (Instruction s = bb.firstRealInstruction(), sentinel = bb.lastInstruction(); s != sentinel; s = s.nextInstructionInCodeOrder()) {
            if (!info.isEmpty()) {
                // PROPAGATE COPIES
                int numUses = s.getNumberOfPureUses();
                if (numUses > 0) {
                    boolean didSomething = false;
                    for (Enumeration<Operand> e = s.getUses(); e.hasMoreElements(); ) {
                        Operand use = e.nextElement();
                        if (use instanceof RegisterOperand) {
                            RegisterOperand rUse = (RegisterOperand) use;
                            Operand value = info.get(rUse.getRegister());
                            if (value != null) {
                                didSomething = true;
                                value = value.copy();
                                if (value instanceof RegisterOperand) {
                                    // preserve program point specific typing!
                                    ((RegisterOperand) value).copyTypeFrom(rUse);
                                }
                                s.replaceOperand(use, value);
                            }
                        }
                    }
                    if (didSomething) {
                        Simplifier.simplify(ir.isHIR(), ir.regpool, ir.options, s);
                    }
                }
                // KILL
                boolean killPhysicals = s.isTSPoint() || s.operator().implicitDefs != 0;
                // premature optimization.
                if (killPhysicals) {
                    HashSet<Register> toRemove = new HashSet<Register>();
                    for (Map.Entry<Register, Operand> entry : info.entrySet()) {
                        Register eR = entry.getValue().asRegister().getRegister();
                        if (killPhysicals && eR.isPhysical()) {
                            // delay the removal to avoid ConcurrentModification with iterator.
                            toRemove.add(entry.getKey());
                        }
                    }
                    // Now perform the removals.
                    for (final Register aToRemove : toRemove) {
                        info.remove(aToRemove);
                    }
                }
                for (Enumeration<Operand> e = s.getDefs(); e.hasMoreElements(); ) {
                    Operand def = e.nextElement();
                    if (def != null && def.isRegister()) {
                        Register r = def.asRegister().getRegister();
                        info.remove(r);
                        // also must kill any registers mapped to r
                        // TODO: use a better data structure for efficiency.
                        // I'm being lazy for now in the name of avoiding
                        // premature optimization.
                        HashSet<Register> toRemove = new HashSet<Register>();
                        for (Map.Entry<Register, Operand> entry : info.entrySet()) {
                            Register eR = ((RegisterOperand) entry.getValue()).getRegister();
                            if (eR == r) {
                                // delay the removal to avoid ConcurrentModification
                                // with iterator.
                                toRemove.add(entry.getKey());
                            }
                        }
                        // Now perform the removals.
                        for (final Register register : toRemove) {
                            info.remove(register);
                        }
                    }
                }
            }
            // GEN
            if (Move.conforms(s)) {
                Operand val = Move.getVal(s);
                if (val.isRegister()) {
                    RegisterOperand rhs = val.asRegister();
                    if (!rhs.getRegister().isPhysical()) {
                        RegisterOperand lhs = Move.getResult(s);
                        /* Only gen if the move instruction does not represent a Magic <==> non-Magic coercion */
                        if (lhs.getType().isReferenceType() == rhs.getType().isReferenceType()) {
                            info.put(lhs.getRegister(), val);
                        }
                    }
                }
            }
        }
        info.clear();
    }
}
Also used : HashMap(java.util.HashMap) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Register(org.jikesrvm.compilers.opt.ir.Register) HashMap(java.util.HashMap) Map(java.util.Map) HashSet(java.util.HashSet)

Example 99 with BasicBlock

use of org.jikesrvm.compilers.opt.ir.BasicBlock 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 100 with BasicBlock

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

the class ComplexLIR2MIRExpansion method long_ushr.

private static Instruction long_ushr(Instruction s, IR ir) {
    Instruction nextInstr = s.nextInstructionInCodeOrder();
    while (Label.conforms(nextInstr) || BBend.conforms(nextInstr)) {
        nextInstr = nextInstr.nextInstructionInCodeOrder();
    }
    // we need 4 basic blocks
    // 1: the current block that does a test if the shift is > 32
    // 2: a block to perform a shift in the range 32 to 63
    // 3: a block to perform a shift in the range 0 to 31
    // 4: the next basic block
    BasicBlock testBB = s.getBasicBlock();
    BasicBlock nextBB = testBB.splitNodeAt(s, ir);
    ir.cfg.linkInCodeOrder(testBB, nextBB);
    BasicBlock shift32BB = testBB.splitNodeAt(s, ir);
    ir.cfg.linkInCodeOrder(testBB, shift32BB);
    BasicBlock shift64BB = testBB.splitNodeAt(s, ir);
    ir.cfg.linkInCodeOrder(testBB, shift64BB);
    // Source registers
    Register lhsReg = Binary.getClearResult(s).getRegister();
    Register lowlhsReg = ir.regpool.getSecondReg(lhsReg);
    Operand val1 = Binary.getClearVal1(s);
    Register rhsReg;
    Register lowrhsReg;
    if (val1.isRegister()) {
        rhsReg = val1.asRegister().getRegister();
        lowrhsReg = ir.regpool.getSecondReg(rhsReg);
    } else {
        // shift is of a constant so set up registers
        int low = val1.asLongConstant().lower32();
        int high = val1.asLongConstant().upper32();
        testBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lowlhsReg, TypeReference.Int), IC(low))));
        testBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lhsReg, TypeReference.Int), IC(high))));
        rhsReg = lhsReg;
        lowrhsReg = lowlhsReg;
    }
    // ecx = shift amount
    Register ecx = phys(ir).getECX();
    testBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(ecx, TypeReference.Int), Binary.getClearVal2(s))));
    // Determine shift of 32 to 63 or 0 to 31
    testBB.appendInstruction(CPOS(s, MIR_Test.create(IA32_TEST, new RegisterOperand(ecx, TypeReference.Int), IC(32))));
    // if (ecx & 32 == 0) goto shift32BB
    testBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, IA32ConditionOperand.EQ(), shift32BB.makeJumpTarget(), BranchProfileOperand.likely())));
    testBB.insertOut(shift32BB);
    // fall-through
    testBB.insertOut(shift64BB);
    // Perform shift in the range 32 to 63
    shift64BB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lowlhsReg, TypeReference.Int), new RegisterOperand(rhsReg, TypeReference.Int))));
    shift64BB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_SHR, new RegisterOperand(lowlhsReg, TypeReference.Int), new RegisterOperand(ecx, TypeReference.Int))));
    shift64BB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lhsReg, TypeReference.Int), IC(0))));
    shift64BB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, nextBB.makeJumpTarget())));
    shift64BB.insertOut(nextBB);
    // Perform shift in the range 0 to 31
    if (lhsReg != rhsReg) {
        shift32BB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lhsReg, TypeReference.Int), new RegisterOperand(rhsReg, TypeReference.Int))));
        shift32BB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lowlhsReg, TypeReference.Int), new RegisterOperand(lowrhsReg, TypeReference.Int))));
    }
    shift32BB.appendInstruction(CPOS(s, MIR_DoubleShift.create(IA32_SHRD, new RegisterOperand(lowlhsReg, TypeReference.Int), new RegisterOperand(lhsReg, TypeReference.Int), new RegisterOperand(ecx, TypeReference.Int))));
    shift32BB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_SHR, new RegisterOperand(lhsReg, TypeReference.Int), new RegisterOperand(ecx, TypeReference.Int))));
    shift32BB.insertOut(nextBB);
    s.remove();
    return nextInstr;
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Register(org.jikesrvm.compilers.opt.ir.Register) 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) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Aggregations

BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)219 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)117 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)93 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)66 ExceptionHandlerBasicBlock (org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock)52 Register (org.jikesrvm.compilers.opt.ir.Register)50 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)48 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)37 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)33 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)27 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)24 HeapOperand (org.jikesrvm.compilers.opt.ir.operand.HeapOperand)21 BasicBlockOperand (org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand)20 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)19 TypeReference (org.jikesrvm.classloader.TypeReference)18 NullConstantOperand (org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand)18 Test (org.junit.Test)17 BranchOperand (org.jikesrvm.compilers.opt.ir.operand.BranchOperand)16 InlineSequence (org.jikesrvm.compilers.opt.inlining.InlineSequence)14 MemoryOperand (org.jikesrvm.compilers.opt.ir.operand.MemoryOperand)14