Search in sources :

Example 81 with Operand

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

the class GenerationContext method completePrologue.

/**
 * Fills in the rest of the method prologue.
 * PRECONDITION: arguments & temps have been setup/initialized.
 *
 * @param isOutermost is this the outermost context (i.e. not an inlined context)
 */
private void completePrologue(boolean isOutermost) {
    // Deal with Uninteruptible code.
    if (!isOutermost && requiresUnintMarker()) {
        Instruction s = Empty.create(UNINT_BEGIN);
        appendInstruction(prologue, s, PROLOGUE_BCI);
    }
    // since it's the second time reenter
    if (method.isForOsrSpecialization()) {
    // do nothing
    } else if (method.isSynchronized() && !options.ESCAPE_INVOKEE_THREAD_LOCAL) {
        Operand lockObject = getLockObject();
        Instruction s = MonitorOp.create(MONITORENTER, lockObject, new TrueGuardOperand());
        appendInstruction(prologue, s, SYNCHRONIZED_MONITORENTER_BCI);
    }
}
Also used : MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) TypeOperand(org.jikesrvm.compilers.opt.ir.operand.TypeOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) ClassConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ClassConstantOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)

Example 82 with Operand

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

the class GenerateMachineSpecificMagic method generateMagic.

/**
 * "Semantic inlining" of methods of the Magic class.
 * Based on the methodName, generate a sequence of opt instructions
 * that implement the magic, updating the stack as necessary
 *
 * @param bc2ir the bc2ir object generating the ir containing this magic
 * @param gc == bc2ir.gc
 * @param meth the RVMMethod that is the magic method
 * @return {@code true} if and only if magic was generated
 */
public static boolean generateMagic(BC2IR bc2ir, GenerationContext gc, MethodReference meth) throws MagicNotImplementedException {
    Atom methodName = meth.getName();
    PhysicalRegisterSet phys = gc.getTemps().getPhysicalRegisterSet().asIA32();
    if (methodName == MagicNames.getESIAsThread) {
        RegisterOperand rop = gc.getTemps().makeTROp();
        bc2ir.markGuardlessNonNull(rop);
        bc2ir.push(rop);
    } else if (methodName == MagicNames.setESIAsThread) {
        Operand val = bc2ir.popRef();
        if (val instanceof RegisterOperand) {
            bc2ir.appendInstruction(Move.create(REF_MOVE, gc.getTemps().makeTROp(), val));
        } else {
            String msg = " Unexpected operand Magic.setESIAsThread";
            throw MagicNotImplementedException.UNEXPECTED(msg);
        }
    } else if (methodName == MagicNames.getFramePointer) {
        gc.forceFrameAllocation();
        RegisterOperand val = gc.getTemps().makeTemp(TypeReference.Address);
        RVMField f = ArchEntrypoints.framePointerField;
        RegisterOperand pr = new RegisterOperand(phys.getESI(), TypeReference.Address);
        bc2ir.appendInstruction(GetField.create(GETFIELD, val, pr.copy(), new AddressConstantOperand(f.getOffset()), new LocationOperand(f), new TrueGuardOperand()));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.getJTOC || methodName == MagicNames.getTocPointer) {
        TypeReference t = (methodName == MagicNames.getJTOC ? TypeReference.IntArray : TypeReference.Address);
        RegisterOperand val = gc.getTemps().makeTemp(t);
        AddressConstantOperand addr = new AddressConstantOperand(Magic.getTocPointer());
        bc2ir.appendInstruction(Move.create(REF_MOVE, val, addr));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.synchronizeInstructionCache) {
    // nothing required on Intel
    } else if (methodName == MagicNames.prefetch) {
        bc2ir.appendInstruction(CacheOp.create(PREFETCH, bc2ir.popAddress()));
    } else if (methodName == MagicNames.pause) {
        bc2ir.appendInstruction(Empty.create(PAUSE));
    } else if (methodName == MagicNames.illegalInstruction) {
        bc2ir.appendInstruction(Empty.create(ILLEGAL_INSTRUCTION));
    } else if (methodName == MagicNames.getCallerFramePointer) {
        Operand fp = bc2ir.popAddress();
        RegisterOperand val = gc.getTemps().makeTemp(TypeReference.Address);
        bc2ir.appendInstruction(Load.create(REF_LOAD, val, fp, offsetOperand(STACKFRAME_FRAME_POINTER_OFFSET), null));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.setCallerFramePointer) {
        Operand val = bc2ir.popAddress();
        Operand fp = bc2ir.popAddress();
        bc2ir.appendInstruction(Store.create(REF_STORE, val, fp, offsetOperand(STACKFRAME_FRAME_POINTER_OFFSET), null));
    } else if (methodName == MagicNames.getCompiledMethodID) {
        Operand fp = bc2ir.popAddress();
        RegisterOperand val = gc.getTemps().makeTempInt();
        bc2ir.appendInstruction(Load.create(INT_LOAD, val, fp, offsetOperand(STACKFRAME_METHOD_ID_OFFSET), null));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.setCompiledMethodID) {
        Operand val = bc2ir.popInt();
        Operand fp = bc2ir.popAddress();
        bc2ir.appendInstruction(Store.create(INT_STORE, val, fp, offsetOperand(STACKFRAME_METHOD_ID_OFFSET), null));
    } else if (methodName == MagicNames.getReturnAddressLocation) {
        Operand fp = bc2ir.popAddress();
        Instruction s = bc2ir._binaryHelper(REF_ADD, fp, offsetOperand(STACKFRAME_RETURN_ADDRESS_OFFSET), TypeReference.Address);
        bc2ir.appendInstruction(s);
    } else {
        // Distinguish between magics that we know we don't implement
        // (and never plan to implement) and those (usually new ones)
        // that we want to be warned that we don't implement.
        String msg = " Magic method not implemented: " + meth;
        if (methodName == MagicNames.returnToNewStack) {
            throw MagicNotImplementedException.EXPECTED(msg);
        } else {
            return false;
        // throw MagicNotImplementedException.UNEXPECTED(msg);
        }
    }
    return true;
}
Also used : LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) IRTools.offsetOperand(org.jikesrvm.compilers.opt.ir.IRTools.offsetOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) PhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.ia32.PhysicalRegisterSet) RVMField(org.jikesrvm.classloader.RVMField) TypeReference(org.jikesrvm.classloader.TypeReference) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) Atom(org.jikesrvm.classloader.Atom) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)

Example 83 with Operand

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

the class AnnotatedLSTNode method getFixedDistanceFromPhiIterator.

/**
 * Get fixed distance from the phi iterator
 *
 * @param op the operand to test
 * @return the fixed distance
 */
public int getFixedDistanceFromPhiIterator(Operand op) {
    if (op.similar(phiLoopIterator)) {
        return 0;
    } else {
        Instruction opInstr = definingInstruction(op);
        if (opInstr.getOpcode() == INT_ADD_opcode) {
            Operand val1 = Binary.getVal1(opInstr);
            Operand val2 = Binary.getVal2(opInstr);
            if (val1.isConstant()) {
                return val1.asIntConstant().value + getFixedDistanceFromPhiIterator(val2);
            } else {
                if (VM.VerifyAssertions)
                    VM._assert(val2.isConstant());
                return getFixedDistanceFromPhiIterator(val1) + val2.asIntConstant().value;
            }
        } else if (opInstr.getOpcode() == INT_SUB_opcode) {
            Operand val1 = Binary.getVal1(opInstr);
            Operand val2 = Binary.getVal2(opInstr);
            if (val1.isConstant()) {
                return val1.asIntConstant().value - getFixedDistanceFromPhiIterator(val2);
            } else {
                if (VM.VerifyAssertions)
                    VM._assert(val2.isConstant());
                return getFixedDistanceFromPhiIterator(val1) - val2.asIntConstant().value;
            }
        }
    }
    throw new Error("Value isn't fixed distance from phi iterator");
}
Also used : BasicBlockOperand(org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) ConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ConstantOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Example 84 with Operand

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

the class BranchOptimizations method generateCondMove.

/**
 * Attempt to generate a straight-line sequence using conditional move
 * instructions, to replace a diamond control flow structure.
 *
 * <p>Suppose we have the following code, where e{n} is an expression:
 * <pre>
 * if (a op b) {
 *   x = e2;
 *   y = e3;
 * } else {
 *   z = e4;
 *   x = e5;
 * }
 * </pre>
 * We would transform this to:
 * <pre>
 * t1 = a;
 * t2 = b;
 * t3 = e2;
 * t4 = e3;
 * t5 = e4;
 * t6 = e5;
 * COND MOVE [if (t1 op t2) x := t3 else x := t6 ];
 * COND MOVE [if (t1 op t2) y := t4 else y := y];
 * COND MOVE [if (t1 op t2) z := z  else z := t5];
 * </pre>
 *
 * <p>Note that we rely on other optimizations (eg. copy propagation) to
 * clean up some of this unnecessary mess.
 *
 * <p>Note that in this example, we've increased the shortest path by 2
 * expression evaluations, 2 moves, and 3 cond moves, but eliminated one
 * conditional branch.
 *
 * <p>We apply a cost heuristic to guide this transformation:
 * We will eliminate a conditional branch iff it increases the shortest
 * path by no more than 'k' operations.  Currently, we count each
 * instruction (alu, move, or cond move) as 1 evaluation.
 * The parameter k is specified by OPT\_Options.COND_MOVE_CUTOFF.
 *
 * <p> In the example above, since we've increased the shortest path by
 * 6 instructions, we will only perform the transformation if {@code k >= 7}.
 *
 * <p> TODO items
 * <ul>
 * <li> consider smarter cost heuristics
 * <li> enhance downstream code generation to avoid redundant evaluation
 * of condition codes.
 * </ul>
 *
 * @param ir governing IR
 * @param bb basic block of cb
 * @param cb conditional branch instruction
 * @return true if the transformation succeeds, false otherwise
 */
private boolean generateCondMove(IR ir, BasicBlock bb, Instruction cb) {
    final boolean VERBOSE = false;
    if (!VM.BuildForIA32)
        return false;
    if (!IfCmp.conforms(cb))
        return false;
    if (VERBOSE)
        System.out.println("CondMove: Looking to optimize " + cb);
    // Don't generate CMOVs for branches that can be folded.
    if (IfCmp.getVal1(cb).isConstant() && IfCmp.getVal2(cb).isConstant()) {
        if (VERBOSE)
            System.out.println("CondMove: fail - could be folded");
        return false;
    }
    // see if bb is the root of an if-then-else.
    Diamond diamond = Diamond.buildDiamond(bb);
    if (diamond == null) {
        if (VERBOSE)
            System.out.println("CondMove: fail - no diamond");
        return false;
    }
    BasicBlock taken = diamond.getTaken();
    BasicBlock notTaken = diamond.getNotTaken();
    // has a taboo instruction (eg., a PEI, store or divide).
    if (taken != null && hasCMTaboo(taken)) {
        if (VERBOSE)
            System.out.println("CondMove: fail - taken branch has taboo instruction");
        return false;
    }
    if (notTaken != null && hasCMTaboo(notTaken)) {
        if (VERBOSE)
            System.out.println("CondMove: fail - not taken branch has taboo instruction");
        return false;
    }
    ConditionOperand cond = IfCmp.getCond(cb);
    // Do not generate when we don't know the branch probability or
    // when branch probability is high. CMOVs reduce performance of
    // the out-of-order engine (Intel Optimization Guide -
    // Assembly/Compiler Coding Rule 2).
    // Ignore in the case of an abs() method as we can create tighter
    // instructions.
    BranchProfileOperand profile = IfCmp.getBranchProfile(cb);
    if ((Math.abs(profile.takenProbability - 0.5) >= ir.options.CONTROL_WELL_PREDICTED_CUTOFF) && !(cb.position() != null && cb.position().method.getName() == ABS && cond.isFLOATINGPOINT())) {
        if (VERBOSE)
            System.out.println("CondMove: fail - branch could be well predicted by branch predictor: " + profile.takenProbability);
        return false;
    }
    // if we must generate FCMP, make sure the condition code is OK
    if (cond.isFLOATINGPOINT()) {
        if (!fpConditionOK(cond)) {
            // Condition not OK, but maybe if we flip the operands
            if (!fpConditionOK(cond.flipOperands())) {
                // still not ok so flip operands back
                cond.flipOperands();
                // controlling just floating point moves
                if (!VM.BuildForSSE2Full || hasFloatingPointDef(taken, true) || hasFloatingPointDef(notTaken, true)) {
                    if (VERBOSE)
                        System.out.println("CondMove: fail - fp condition not OK: " + cond);
                    return false;
                }
            } else {
                // flip operands
                Operand val1 = IfCmp.getVal1(cb);
                Operand val2 = IfCmp.getVal2(cb);
                IfCmp.setVal1(cb, val2);
                IfCmp.setVal2(cb, val1);
            }
        }
    }
    if (!cond.isFLOATINGPOINT()) {
        // compares or for unsigned compares in x87
        if (VM.BuildForSSE2Full || !cond.isUNSIGNED()) {
            if (hasFloatingPointDef(taken, false) || hasFloatingPointDef(notTaken, false)) {
                if (VERBOSE)
                    System.out.println("CondMove: fail - not allowed integer condition controlling floating conditional move");
                return false;
            }
        }
    }
    // For now, do not generate CMOVs for longs.
    if (hasLongDef(taken) || hasLongDef(notTaken)) {
        return false;
    }
    // count the number of expression evaluations in each side of the
    // diamond
    int takenCost = 0;
    int notTakenCost = 0;
    if (taken != null)
        takenCost = evaluateCost(taken);
    if (notTaken != null)
        notTakenCost = evaluateCost(notTaken);
    // evaluate whether it's profitable.
    int shortestCost = Math.min(takenCost, notTakenCost);
    int xformCost = 2 * (takenCost + notTakenCost);
    int k = ir.options.CONTROL_COND_MOVE_CUTOFF;
    if (xformCost - shortestCost > k) {
        if (VERBOSE)
            System.out.println("CondMove: fail - cost too high");
        return false;
    }
    // Perform the transformation!
    doCondMove(ir, diamond, cb);
    return true;
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand) 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)

Example 85 with Operand

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

Aggregations

Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)355 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)328 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)242 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)217 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)212 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)210 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)207 TrapCodeOperand (org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand)185 LongConstantOperand (org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand)174 ConstantOperand (org.jikesrvm.compilers.opt.ir.operand.ConstantOperand)165 TypeOperand (org.jikesrvm.compilers.opt.ir.operand.TypeOperand)153 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)144 AddressConstantOperand (org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand)143 NullConstantOperand (org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand)141 ObjectConstantOperand (org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand)128 TIBConstantOperand (org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand)121 UnreachableOperand (org.jikesrvm.compilers.opt.ir.operand.UnreachableOperand)117 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)102 CodeConstantOperand (org.jikesrvm.compilers.opt.ir.operand.CodeConstantOperand)98 Register (org.jikesrvm.compilers.opt.ir.Register)82