Search in sources :

Example 21 with OptimizingCompilerException

use of org.jikesrvm.compilers.opt.OptimizingCompilerException in project JikesRVM by JikesRVM.

the class BURS_Helpers method LONG_USHR.

/**
 * Expansion of LONG_USHR
 * @param s the instruction to expand
 * @param result the result operand
 * @param val1 the shifted operand
 * @param val2 the shift amount operand
 * @param maskWith3f should the shift operand by masked with 0x3f? This is
 *          default behaviour on Intel but it differs from how we combine
 *          shift operands in HIR
 */
protected final void LONG_USHR(Instruction s, Operand result, Operand val1, Operand val2, boolean maskWith3f) {
    if (!val2.isIntConstant()) {
        // the most efficient form of expanding a shift by a variable amount
        // requires a branch so leave for complex operators
        // NB if !maskWith3f - we assume that a mask with 0x3F was required as
        // no optimizations currently exploits shift by registers of > 63
        // returning 0
        Binary.mutate(s, LONG_USHR, result.asRegister(), val1, val2);
        EMIT(s);
    } else if (result.isRegister()) {
        int shift = val2.asIntConstant().value;
        if (maskWith3f) {
            shift = shift & 0x3F;
        }
        Register lhsReg = result.asRegister().getRegister();
        Register lowlhsReg = burs.ir.regpool.getSecondReg(lhsReg);
        Register rhsReg1 = val1.asRegister().getRegister();
        Register lowrhsReg1 = burs.ir.regpool.getSecondReg(rhsReg1);
        if (shift == 0) {
            // operation is a nop.
            if (!result.similar(val1)) {
                EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lowlhsReg, TypeReference.Int), new RegisterOperand(lowrhsReg1, TypeReference.Int))));
                EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lhsReg, TypeReference.Int), new RegisterOperand(rhsReg1, TypeReference.Int))));
            }
        } else if (shift == 1) {
            if (!result.similar(val1)) {
                EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lowlhsReg, TypeReference.Int), new RegisterOperand(lowrhsReg1, TypeReference.Int))));
                EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lhsReg, TypeReference.Int), new RegisterOperand(rhsReg1, TypeReference.Int))));
            }
            // lhsReg = lhsReg >>> 1
            EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SHR, new RegisterOperand(lhsReg, TypeReference.Int), IC(1))));
            // lowlhsReg = (lhsReg << 31) | (lowlhsReg >>> 1)
            EMIT(MIR_BinaryAcc.mutate(s, IA32_RCR, new RegisterOperand(lowlhsReg, TypeReference.Int), IC(1)));
        } else if (shift < 32) {
            // bits to shift in: tmp = rhsReg << (32 - shift)
            // TODO: use LEA for SHL operator
            Register tmp = regpool.getInteger();
            EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(tmp, TypeReference.Int), new RegisterOperand(rhsReg1, TypeReference.Int))));
            EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SHL, new RegisterOperand(tmp, TypeReference.Int), IC(32 - shift))));
            // compute bottom half: lowlhsReg = (lowlhsReg1 >>> shift) | tmp
            if (!result.similar(val1)) {
                EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lowlhsReg, TypeReference.Int), new RegisterOperand(lowrhsReg1, TypeReference.Int))));
            }
            EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SHR, new RegisterOperand(lowlhsReg, TypeReference.Int), IC(shift))));
            EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_OR, new RegisterOperand(lowlhsReg, TypeReference.Int), new RegisterOperand(tmp, TypeReference.Int))));
            // compute top half: lhsReg = lhsReg >>> shift
            if (!result.similar(val1)) {
                EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lhsReg, TypeReference.Int), new RegisterOperand(rhsReg1, TypeReference.Int))));
            }
            EMIT(MIR_BinaryAcc.mutate(s, IA32_SHR, new RegisterOperand(lhsReg, TypeReference.Int), IC(shift)));
        } else if (shift == 32) {
            // lowlhsReg = rhsReg1
            EMIT(MIR_Move.mutate(s, IA32_MOV, new RegisterOperand(lowlhsReg, TypeReference.Int), new RegisterOperand(rhsReg1, TypeReference.Int)));
            // lhsReg = 0
            EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lhsReg, TypeReference.Int), IC(0))));
        } else {
            if (maskWith3f || (shift < 64)) {
                // lowlhsReg = rhsReg1 >>> (shift & 0x1F)
                EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lowlhsReg, TypeReference.Int), new RegisterOperand(rhsReg1, TypeReference.Int))));
                EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SHR, new RegisterOperand(lowlhsReg, TypeReference.Int), IC(shift & 0x1F))));
            } else {
                // lowlhsReg = 0
                EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lowlhsReg, TypeReference.Int), IC(0))));
            }
            // lhsReg = 0
            EMIT(MIR_Move.mutate(s, IA32_MOV, new RegisterOperand(lhsReg, TypeReference.Int), IC(0)));
        }
    } else {
        throw new OptimizingCompilerException("BURS_Helpers", "unexpected parameters: " + result + "=" + val1 + ">>" + val2);
    }
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Register(org.jikesrvm.compilers.opt.ir.Register) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException)

Example 22 with OptimizingCompilerException

use of org.jikesrvm.compilers.opt.OptimizingCompilerException in project JikesRVM by JikesRVM.

the class BURS_MemOp_Helpers method combineAddresses.

protected final void combineAddresses() {
    if (VM.VerifyAssertions)
        VM._assert(AddrStack != null, "No address to combine");
    AddrStackElement tmp = AddrStack;
    AddrStack = AddrStack.next;
    if (VM.VerifyAssertions)
        VM._assert(AddrStack != null, "only 1 address to combine");
    if (tmp.base != null) {
        if (AddrStack.base == null) {
            AddrStack.base = tmp.base;
        } else if (AddrStack.index == null) {
            if (VM.VerifyAssertions)
                VM._assert(AddrStack.scale == (byte) 0);
            AddrStack.index = tmp.base;
        } else {
            throw new OptimizingCompilerException("three base registers in address");
        }
    }
    if (tmp.index != null) {
        if (AddrStack.index == null) {
            if (VM.VerifyAssertions)
                VM._assert(AddrStack.scale == (byte) 0);
            AddrStack.index = tmp.index;
            AddrStack.scale = tmp.scale;
        } else if (AddrStack.base == null && tmp.scale == (byte) 0) {
            AddrStack.base = tmp.base;
        } else {
            throw new OptimizingCompilerException("two scaled registers in address");
        }
    }
    AddrStack.displacement = AddrStack.displacement.plus(tmp.displacement);
}
Also used : OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException)

Example 23 with OptimizingCompilerException

use of org.jikesrvm.compilers.opt.OptimizingCompilerException 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)

Example 24 with OptimizingCompilerException

use of org.jikesrvm.compilers.opt.OptimizingCompilerException in project JikesRVM by JikesRVM.

the class LeaveSSA method scheduleCopies.

/**
 * Record pending copy operations needed to insert at the end of a basic
 * block.<p>
 *
 * TODO: this procedure is getting long and ugly.  Rewrite or refactor
 * it.
 * @param bb the basic block to process
 * @param live valid liveness information for the IR
 */
private void scheduleCopies(BasicBlock bb, LiveAnalysis live) {
    if (DEBUG)
        VM.sysWriteln("scheduleCopies: " + bb);
    // compute out liveness from information in LiveAnalysis
    LiveSet out = new LiveSet();
    for (Enumeration<BasicBlock> outBlocks = bb.getOut(); outBlocks.hasMoreElements(); ) {
        BasicBlock ob = outBlocks.nextElement();
        LiveAnalysis.BBLiveElement le = live.getLiveInfo(ob);
        out.add(le.getIn());
    }
    // usedByAnother represents the set of registers that appear on the
    // left-hand side of subsequent phi nodes.  This is important, since
    // we be careful to order copies if the same register appears as the
    // source and dest of copies in the same basic block.
    HashSet<Register> usedByAnother = new HashSet<Register>(4);
    // for each basic block successor b of bb, if we make a block on the
    // critical edge bb->b, then store this critical block.
    HashMap<BasicBlock, BasicBlock> criticalBlocks = new HashMap<BasicBlock, BasicBlock>(4);
    // For each critical basic block b in which we are inserting copies: return the
    // mapping of registers to names implied by the copies that have
    // already been inserted into b.
    HashMap<BasicBlock, HashMap<Register, Register>> currentNames = new HashMap<BasicBlock, HashMap<Register, Register>>(4);
    // Additionally store the current names for the current basic block bb.
    HashMap<Register, Register> bbNames = new HashMap<Register, Register>(4);
    // copySet is a linked-list of copies we need to insert in this block.
    final LinkedList<Copy> copySet = new LinkedList<Copy>();
    /* Worklist is actually used like a stack - should we make this an Stack ?? */
    final LinkedList<Copy> workList = new LinkedList<Copy>();
    // collect copies required in this block.  These copies move
    // the appropriate rval into the lval of each phi node in
    // control children of the current block.
    Enumeration<BasicBlock> e = bb.getOut();
    while (e.hasMoreElements()) {
        BasicBlock bbs = e.nextElement();
        if (bbs.isExit())
            continue;
        for (Instruction phi = bbs.firstInstruction(); phi != bbs.lastInstruction(); phi = phi.nextInstructionInCodeOrder()) {
            if (phi.operator() != PHI)
                continue;
            for (int index = 0; index < Phi.getNumberOfPreds(phi); index++) {
                if (Phi.getPred(phi, index).block != bb)
                    continue;
                Operand rval = Phi.getValue(phi, index);
                if (rval.isRegister() && Phi.getResult(phi).asRegister().getRegister() == rval.asRegister().getRegister()) {
                    continue;
                }
                Copy c = new Copy(phi, index);
                copySet.add(0, c);
                if (c.source instanceof RegisterOperand) {
                    Register r = c.source.asRegister().getRegister();
                    usedByAnother.add(r);
                }
            }
        }
    }
    // the set of needed copies.
    for (Iterator<Copy> copySetIter = copySet.iterator(); copySetIter.hasNext(); ) {
        Copy c = copySetIter.next();
        if (!usedByAnother.contains(c.destination.getRegister())) {
            workList.add(0, c);
            copySetIter.remove();
        }
    }
    // while there is any more work to do.
    while (!workList.isEmpty() || !copySet.isEmpty()) {
        // while there are copies that can be correctly inserted.
        while (!workList.isEmpty()) {
            Copy c = workList.remove(0);
            Register r = c.destination.getRegister();
            TypeReference tt = c.destination.getType();
            if (VM.VerifyAssertions && tt == null) {
                tt = TypeReference.Int;
                VM.sysWriteln("SSA, warning: null type in " + c.destination);
            }
            Register rr = null;
            if (c.source.isRegister())
                rr = c.source.asRegister().getRegister();
            boolean shouldSplitBlock = !c.phi.getBasicBlock().isExceptionHandlerBasicBlock() && ((ir.options.SSA_SPLITBLOCK_TO_AVOID_RENAME && out.contains(r)) || (rr != null && ir.options.SSA_SPLITBLOCK_FOR_LOCAL_LIVE && usedBelowCopy(bb, rr)));
            if (ir.options.SSA_SPLITBLOCK_INTO_INFREQUENT) {
                if (!bb.getInfrequent() && c.phi.getBasicBlock().getInfrequent() && !c.phi.getBasicBlock().isExceptionHandlerBasicBlock()) {
                    shouldSplitBlock = true;
                }
            }
            // new name.
            if (out.contains(r) && !shouldSplitBlock) {
                if (!globalRenamePhis.contains(r)) {
                    Register t = ir.regpool.getReg(r);
                    Instruction save = SSA.makeMoveInstruction(ir, t, r, tt);
                    if (DEBUG) {
                        VM.sysWriteln("Inserting " + save + " before " + c.phi + " in " + c.phi.getBasicBlock());
                    }
                    c.phi.insertAfter(save);
                    globalRenamePhis.add(r);
                    globalRenameTable.add(save);
                }
            }
            Instruction ci = null;
            // insert copy operation required to remove phi
            if (c.source instanceof ConstantOperand) {
                if (c.source instanceof UnreachableOperand) {
                    ci = null;
                } else {
                    ci = SSA.makeMoveInstruction(ir, r, (ConstantOperand) c.source);
                }
            } else if (c.source instanceof RegisterOperand) {
                if (shouldSplitBlock) {
                    if (DEBUG)
                        VM.sysWriteln("splitting edge: " + bb + "->" + c.phi.getBasicBlock());
                    BasicBlock criticalBlock = criticalBlocks.get(c.phi.getBasicBlock());
                    if (criticalBlock == null) {
                        criticalBlock = IRTools.makeBlockOnEdge(bb, c.phi.getBasicBlock(), ir);
                        if (c.phi.getBasicBlock().getInfrequent()) {
                            criticalBlock.setInfrequent();
                        }
                        splitSomeBlock = true;
                        criticalBlocks.put(c.phi.getBasicBlock(), criticalBlock);
                        HashMap<Register, Register> newNames = new HashMap<Register, Register>(4);
                        currentNames.put(criticalBlock, newNames);
                    }
                    Register sr = c.source.asRegister().getRegister();
                    HashMap<Register, Register> criticalBlockNames = currentNames.get(criticalBlock);
                    Register nameForSR = criticalBlockNames.get(sr);
                    if (nameForSR == null) {
                        nameForSR = bbNames.get(sr);
                        if (nameForSR == null)
                            nameForSR = sr;
                    }
                    if (DEBUG)
                        VM.sysWriteln("dest(r): " + r);
                    if (DEBUG)
                        VM.sysWriteln("sr: " + sr + ", nameForSR: " + nameForSR);
                    ci = SSA.makeMoveInstruction(ir, r, nameForSR, tt);
                    criticalBlockNames.put(sr, r);
                    criticalBlock.appendInstructionRespectingTerminalBranch(ci);
                } else {
                    Register sr = c.source.asRegister().getRegister();
                    Register nameForSR = bbNames.get(sr);
                    if (nameForSR == null)
                        nameForSR = sr;
                    if (DEBUG)
                        VM.sysWriteln("not splitting edge: " + bb + "->" + c.phi.getBasicBlock());
                    if (DEBUG)
                        VM.sysWriteln("dest(r): " + r);
                    if (DEBUG)
                        VM.sysWriteln("sr: " + sr + ", nameForSR: " + nameForSR);
                    ci = SSA.makeMoveInstruction(ir, r, nameForSR, tt);
                    bbNames.put(sr, r);
                    SSA.addAtEnd(ir, bb, ci, c.phi.getBasicBlock().isExceptionHandlerBasicBlock());
                }
                // ugly hack: having already added ci; set ci to null to skip remaining code;
                ci = null;
            } else {
                throw new OptimizingCompilerException("Unexpected phi operand " + c.source + " encountered during SSA teardown", true);
            }
            if (ci != null) {
                if (shouldSplitBlock) {
                    if (DEBUG)
                        VM.sysWriteln("splitting edge: " + bb + "->" + c.phi.getBasicBlock());
                    BasicBlock criticalBlock = criticalBlocks.get(c.phi.getBasicBlock());
                    if (criticalBlock == null) {
                        criticalBlock = IRTools.makeBlockOnEdge(bb, c.phi.getBasicBlock(), ir);
                        if (c.phi.getBasicBlock().getInfrequent()) {
                            criticalBlock.setInfrequent();
                        }
                        splitSomeBlock = true;
                        criticalBlocks.put(c.phi.getBasicBlock(), criticalBlock);
                        HashMap<Register, Register> newNames = new HashMap<Register, Register>(4);
                        currentNames.put(criticalBlock, newNames);
                    }
                    criticalBlock.appendInstructionRespectingTerminalBranch(ci);
                } else {
                    SSA.addAtEnd(ir, bb, ci, c.phi.getBasicBlock().isExceptionHandlerBasicBlock());
                }
            }
            // current copy to the work list.
            if (c.source instanceof RegisterOperand) {
                Register saved = c.source.asRegister().getRegister();
                Iterator<Copy> copySetIter = copySet.iterator();
                while (copySetIter.hasNext()) {
                    Copy cc = copySetIter.next();
                    if (cc.destination.asRegister().getRegister() == saved) {
                        workList.add(0, cc);
                        copySetIter.remove();
                    }
                }
            }
        }
        // safely overwritten.  so, add that copy to the work list.
        if (!copySet.isEmpty()) {
            Copy c = copySet.remove(0);
            Register tt = ir.regpool.getReg(c.destination.getRegister());
            SSA.addAtEnd(ir, bb, SSA.makeMoveInstruction(ir, tt, c.destination.getRegister(), c.destination.getType()), c.phi.getBasicBlock().isExceptionHandlerBasicBlock());
            bbNames.put(c.destination.getRegister(), tt);
            workList.add(0, c);
        }
    }
}
Also used : LiveSet(org.jikesrvm.compilers.opt.liveness.LiveSet) HashMap(java.util.HashMap) UnreachableOperand(org.jikesrvm.compilers.opt.ir.operand.UnreachableOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) ConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ConstantOperand) UnreachableOperand(org.jikesrvm.compilers.opt.ir.operand.UnreachableOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TypeReference(org.jikesrvm.classloader.TypeReference) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException) HashSet(java.util.HashSet) ConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ConstantOperand) LiveAnalysis(org.jikesrvm.compilers.opt.liveness.LiveAnalysis) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) LinkedList(java.util.LinkedList) Register(org.jikesrvm.compilers.opt.ir.Register)

Example 25 with OptimizingCompilerException

use of org.jikesrvm.compilers.opt.OptimizingCompilerException in project JikesRVM by JikesRVM.

the class LoadElimination method replaceDefs.

/**
 * Perform scalar replacement actions for a Def of a heap variable.
 * <p>
 * NOTE: Even loads can def a heap variable.
 *
 * @param ir the governing IR
 * @param UseRepSet stores the uses(loads) that have been eliminated
 * @param registers mapping from valueNumber -&gt; temporary register
 */
static void replaceDefs(IR ir, UseRecordSet UseRepSet, HashMap<UseRecord, Register> registers) {
    SSADictionary ssa = ir.HIRInfo.dictionary;
    for (Enumeration<Instruction> e = ir.forwardInstrEnumerator(); e.hasMoreElements(); ) {
        Instruction s = e.nextElement();
        if (!GetField.conforms(s) && !GetStatic.conforms(s) && !PutField.conforms(s) && !PutStatic.conforms(s) && !ALoad.conforms(s) && !AStore.conforms(s)) {
            continue;
        }
        if (!ssa.defsHeapVariable(s)) {
            continue;
        }
        // this instruction is a DEF of heap variable H.
        // Check if UseRepSet needs the scalar assigned by this def
        HeapOperand<?>[] H = ssa.getHeapDefs(s);
        if (H.length != 1) {
            throw new OptimizingCompilerException("LoadElimination: encountered a store with more than one def? " + s);
        }
        int valueNumber = -1;
        Object index = null;
        if (AStore.conforms(s)) {
            Object address = AStore.getArray(s);
            index = AStore.getIndex(s);
            valueNumber = ir.HIRInfo.valueNumbers.getValueNumber(address);
        } else if (GetField.conforms(s)) {
            Object address = GetField.getRef(s);
            valueNumber = ir.HIRInfo.valueNumbers.getValueNumber(address);
        } else if (PutField.conforms(s)) {
            Object address = PutField.getRef(s);
            valueNumber = ir.HIRInfo.valueNumbers.getValueNumber(address);
        } else if (GetStatic.conforms(s)) {
            valueNumber = 0;
        } else if (PutStatic.conforms(s)) {
            valueNumber = 0;
        } else if (ALoad.conforms(s)) {
            Object address = ALoad.getArray(s);
            valueNumber = ir.HIRInfo.valueNumbers.getValueNumber(address);
            index = ALoad.getIndex(s);
        }
        if (index == null) {
            // Load/Store
            if (UseRepSet.containsMatchingUse(H[0].getHeapVariable(), valueNumber)) {
                Operand value = null;
                if (PutField.conforms(s)) {
                    value = PutField.getValue(s);
                } else if (PutStatic.conforms(s)) {
                    value = PutStatic.getValue(s);
                } else if (GetField.conforms(s) || GetStatic.conforms(s)) {
                    value = ResultCarrier.getResult(s);
                }
                TypeReference type = value.getType();
                Register r = findOrCreateRegister(H[0].getHeapType(), valueNumber, registers, ir.regpool, type);
                appendMove(r, value, s);
            }
        } else {
            // ALoad / AStore
            int v1 = valueNumber;
            int v2 = ir.HIRInfo.valueNumbers.getValueNumber(index);
            if (UseRepSet.containsMatchingUse(H[0].getHeapVariable(), v1, v2)) {
                Operand value = null;
                if (AStore.conforms(s)) {
                    value = AStore.getValue(s);
                } else if (ALoad.conforms(s)) {
                    value = ALoad.getResult(s);
                }
                TypeReference type = value.getType();
                Register r = findOrCreateRegister(H[0].getHeapType(), v1, v2, registers, ir.regpool, type);
                appendMove(r, value, s);
            }
        }
    }
}
Also used : HeapOperand(org.jikesrvm.compilers.opt.ir.operand.HeapOperand) Register(org.jikesrvm.compilers.opt.ir.Register) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) HeapOperand(org.jikesrvm.compilers.opt.ir.operand.HeapOperand) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException) TypeReference(org.jikesrvm.classloader.TypeReference) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Aggregations

OptimizingCompilerException (org.jikesrvm.compilers.opt.OptimizingCompilerException)47 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)25 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)18 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)17 Register (org.jikesrvm.compilers.opt.ir.Register)16 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)14 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)11 LongConstantOperand (org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand)11 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)11 TrapCodeOperand (org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand)10 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)10 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)9 ConstantOperand (org.jikesrvm.compilers.opt.ir.operand.ConstantOperand)9 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)9 TypeReference (org.jikesrvm.classloader.TypeReference)8 AddressConstantOperand (org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand)8 BranchOperand (org.jikesrvm.compilers.opt.ir.operand.BranchOperand)8 DoubleConstantOperand (org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand)6 FloatConstantOperand (org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand)6 Offset (org.vmmagic.unboxed.Offset)6