Search in sources :

Example 31 with Instruction

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

the class BURS_Helpers method LONG_STORE_addi.

protected final void LONG_STORE_addi(Instruction s, RegisterOperand def, RegisterOperand left, IntConstantOperand right, LocationOperand loc, Operand guard) {
    if (VM.VerifyAssertions)
        VM._assert(VM.BuildFor32Addr);
    Register defHigh = def.getRegister();
    Register defLow = regpool.getSecondReg(defHigh);
    int imm = right.value;
    if (VM.VerifyAssertions) {
        VM._assert(imm < (0x8000 - 4));
    }
    Instruction inst = MIR_Store.create(PPC_STW, I(defHigh), left, IC(imm), loc, guard);
    inst.copyPosition(s);
    EMIT(inst);
    if (loc != null) {
        loc = (LocationOperand) loc.copy();
    }
    if (guard != null) {
        guard = guard.copy();
    }
    inst = MIR_Store.create(PPC_STW, I(defLow), left.copyU2U(), IC(imm + 4), loc, guard);
    inst.copyPosition(s);
    EMIT(inst);
}
Also used : Register(org.jikesrvm.compilers.opt.ir.Register) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) OsrPoint(org.jikesrvm.compilers.opt.ir.OsrPoint)

Example 32 with Instruction

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

the class NormalizeConstants method perform.

/**
 * Doit.
 *
 * @param ir IR to normalize
 */
public static void perform(IR ir) {
    // This greatly reduces the number of cases we have to worry about below.
    if (VM.VerifyAssertions)
        VM._assert(ir.options.SIMPLIFY_INTEGER_OPS && ir.options.SIMPLIFY_LONG_OPS && ir.options.SIMPLIFY_REF_OPS);
    for (Instruction s = ir.firstInstructionInCodeOrder(); s != null; s = s.nextInstructionInCodeOrder()) {
        // STEP ONE: Get 'large' constants into a form that the PPC BURS rules
        // are prepared to deal with.
        // Constants can't appear as defs, so only scan the uses.
        // 
        int numUses = s.getNumberOfUses();
        if (numUses > 0) {
            int numDefs = s.getNumberOfDefs();
            for (int idx = numDefs; idx < numUses + numDefs; idx++) {
                Operand use = s.getOperand(idx);
                if (use != null) {
                    if (use instanceof ObjectConstantOperand) {
                        RegisterOperand rop = ir.regpool.makeTemp(use.getType());
                        RegisterOperand jtoc = (RegisterOperand) ir.regpool.makeJTOCOp();
                        ObjectConstantOperand oc = (ObjectConstantOperand) use;
                        Offset offset = oc.offset;
                        if (offset.isZero()) {
                            if (use instanceof StringConstantOperand) {
                                throw new OptimizingCompilerException("String constant w/o valid JTOC offset");
                            } else if (use instanceof ClassConstantOperand) {
                                throw new OptimizingCompilerException("Class constant w/o valid JTOC offset");
                            }
                            offset = Offset.fromIntSignExtend(Statics.findOrCreateObjectLiteral(oc.value));
                        }
                        LocationOperand loc = new LocationOperand(offset);
                        s.insertBefore(Load.create(VM.BuildFor32Addr ? INT_LOAD : LONG_LOAD, rop, jtoc, asImmediateOrRegOffset(AC(offset), s, ir, true), loc));
                        s.putOperand(idx, rop.copyD2U());
                    } else if (use instanceof DoubleConstantOperand) {
                        RegisterOperand rop = ir.regpool.makeTemp(TypeReference.Double);
                        RegisterOperand jtoc = (RegisterOperand) ir.regpool.makeJTOCOp();
                        DoubleConstantOperand dc = (DoubleConstantOperand) use;
                        Offset offset = dc.offset;
                        if (offset.isZero()) {
                            offset = Offset.fromIntSignExtend(Statics.findOrCreateLongSizeLiteral(Double.doubleToLongBits(dc.value)));
                        }
                        LocationOperand loc = new LocationOperand(offset);
                        s.insertBefore(Load.create(DOUBLE_LOAD, rop, jtoc, asImmediateOrRegOffset(AC(offset), s, ir, true), loc));
                        s.putOperand(idx, rop.copyD2U());
                    } else if (use instanceof FloatConstantOperand) {
                        RegisterOperand rop = ir.regpool.makeTemp(TypeReference.Float);
                        RegisterOperand jtoc = (RegisterOperand) ir.regpool.makeJTOCOp();
                        FloatConstantOperand fc = (FloatConstantOperand) use;
                        Offset offset = fc.offset;
                        if (offset.isZero()) {
                            offset = Offset.fromIntSignExtend(Statics.findOrCreateIntSizeLiteral(Float.floatToIntBits(fc.value)));
                        }
                        LocationOperand loc = new LocationOperand(offset);
                        s.insertBefore(Load.create(FLOAT_LOAD, rop, jtoc, asImmediateOrRegOffset(AC(offset), s, ir, true), loc));
                        s.putOperand(idx, rop.copyD2U());
                    } else if (use instanceof LongConstantOperand) {
                        if (!VM.BuildFor64Addr) {
                            if (s.getOpcode() != TRAP_IF_opcode) {
                                RegisterOperand rop = ir.regpool.makeTemp(TypeReference.Long);
                                s.insertBefore(Move.create(LONG_MOVE, rop, use.copy()));
                                s.putOperand(idx, rop.copyD2U());
                            }
                        }
                    } else if (use instanceof NullConstantOperand) {
                        s.putOperand(idx, AC(Address.zero()));
                    } else if (use instanceof TIBConstantOperand) {
                        RegisterOperand rop = ir.regpool.makeTemp(TypeReference.JavaLangObjectArray);
                        Operand jtoc = ir.regpool.makeJTOCOp();
                        Offset offset = ((TIBConstantOperand) use).value.getTibOffset();
                        LocationOperand loc = new LocationOperand(offset);
                        s.insertBefore(Load.create(VM.BuildFor32Addr ? INT_LOAD : LONG_LOAD, rop, jtoc, asImmediateOrRegOffset(AC(offset), s, ir, true), loc));
                        s.putOperand(idx, rop.copyD2U());
                    } else if (use instanceof CodeConstantOperand) {
                        RegisterOperand rop = ir.regpool.makeTemp(TypeReference.CodeArray);
                        Operand jtoc = ir.regpool.makeJTOCOp();
                        Offset offset = ((CodeConstantOperand) use).value.findOrCreateJtocOffset();
                        LocationOperand loc = new LocationOperand(offset);
                        s.insertBefore(Load.create(VM.BuildFor32Addr ? INT_LOAD : LONG_LOAD, rop, jtoc, asImmediateOrRegOffset(AC(offset), s, ir, true), loc));
                        s.putOperand(idx, rop.copyD2U());
                    }
                }
            }
        }
        // Calling Simplifier.simplify ensures that the instruction is
        // in normalized form. This reduces the number of cases we have to
        // worry about (and does last minute constant folding on the off chance
        // we've missed an opportunity...)
        Simplifier.simplify(false, ir.regpool, ir.options, s);
        switch(s.getOpcode()) {
            // ////////
            case REF_STORE_opcode:
                s.changeOperatorTo(VM.BuildFor32Addr ? INT_STORE : LONG_STORE);
                // On PowerPC, the value being stored must be in a register
                Store.setValue(s, asRegPolymorphic(Store.getClearValue(s), s, ir));
                // Supported addressing modes are quite limited.
                Store.setAddress(s, asRegAddress(Store.getClearAddress(s), s, ir));
                Store.setOffset(s, asImmediateOrRegOffset(Store.getClearOffset(s), s, ir, true));
                break;
            case BYTE_STORE_opcode:
            case SHORT_STORE_opcode:
            case INT_STORE_opcode:
            case LONG_STORE_opcode:
                // On PowerPC, the value being stored must be in a register
                Store.setValue(s, asRegPolymorphic(Store.getClearValue(s), s, ir));
                // Supported addressing modes are quite limited.
                Store.setAddress(s, asRegAddress(Store.getClearAddress(s), s, ir));
                Store.setOffset(s, asImmediateOrRegOffset(Store.getClearOffset(s), s, ir, true));
                break;
            case FLOAT_STORE_opcode:
            case DOUBLE_STORE_opcode:
                // Supported addressing modes are quite limited.
                Store.setAddress(s, asRegAddress(Store.getClearAddress(s), s, ir));
                Store.setOffset(s, asImmediateOrRegOffset(Store.getClearOffset(s), s, ir, true));
                break;
            case REF_LOAD_opcode:
                s.changeOperatorTo(VM.BuildFor32Addr ? INT_LOAD : LONG_LOAD);
                // Supported addressing modes are quite limited.
                Load.setAddress(s, asRegAddress(Load.getClearAddress(s), s, ir));
                Load.setOffset(s, asImmediateOrRegOffset(Load.getClearOffset(s), s, ir, true));
                break;
            case BYTE_LOAD_opcode:
            case UBYTE_LOAD_opcode:
            case SHORT_LOAD_opcode:
            case USHORT_LOAD_opcode:
            case INT_LOAD_opcode:
            case LONG_LOAD_opcode:
            case FLOAT_LOAD_opcode:
            case DOUBLE_LOAD_opcode:
                // Supported addressing modes are quite limited.
                Load.setAddress(s, asRegAddress(Load.getClearAddress(s), s, ir));
                Load.setOffset(s, asImmediateOrRegOffset(Load.getClearOffset(s), s, ir, true));
                break;
            case ATTEMPT_INT_opcode:
            case ATTEMPT_LONG_opcode:
            case ATTEMPT_ADDR_opcode:
                // On PowerPC, the value being stored must be in a register
                Attempt.setNewValue(s, asRegPolymorphic(Attempt.getClearNewValue(s), s, ir));
                // not used on powerpc.
                Attempt.setOldValue(s, null);
                // Supported addressing modes are quite limited.
                Attempt.setAddress(s, asRegAddress(Attempt.getClearAddress(s), s, ir));
                Attempt.setOffset(s, asRegOffset(Attempt.getClearOffset(s), s, ir));
                break;
            case PREPARE_INT_opcode:
            case PREPARE_LONG_opcode:
            case PREPARE_ADDR_opcode:
                // Supported addressing modes are quite limited.
                Prepare.setAddress(s, asRegAddress(Prepare.getClearAddress(s), s, ir));
                Prepare.setOffset(s, asRegOffset(Prepare.getClearOffset(s), s, ir));
                break;
            case LONG_MOVE_opcode:
                if (VM.BuildFor64Addr) {
                    s.changeOperatorTo(REF_MOVE);
                }
                break;
            case INT_MOVE_opcode:
                s.changeOperatorTo(REF_MOVE);
                break;
            case REF_COND_MOVE_opcode:
                s.changeOperatorTo(VM.BuildFor32Addr ? INT_COND_MOVE : LONG_COND_MOVE);
                break;
            case REF_IFCMP_opcode:
                s.changeOperatorTo(VM.BuildFor32Addr ? INT_IFCMP : LONG_IFCMP);
                // val1 can't be a constant, val2 must be small enough.
                IfCmp.setVal1(s, asRegPolymorphic(IfCmp.getClearVal1(s), s, ir));
                IfCmp.setVal2(s, asImmediateOrRegPolymorphic(IfCmp.getClearVal2(s), s, ir, true));
            case LONG_IFCMP_opcode:
                if (VM.BuildFor64Addr) {
                    // val1 can't be a constant, val2 must be small enough.
                    IfCmp.setVal1(s, asRegPolymorphic(IfCmp.getClearVal1(s), s, ir));
                    IfCmp.setVal2(s, asImmediateOrRegPolymorphic(IfCmp.getClearVal2(s), s, ir, true));
                }
                break;
            case INT_IFCMP_opcode:
                // val1 can't be a constant, val2 must be small enough.
                IfCmp.setVal1(s, asRegPolymorphic(IfCmp.getClearVal1(s), s, ir));
                IfCmp.setVal2(s, asImmediateOrRegPolymorphic(IfCmp.getClearVal2(s), s, ir, true));
                break;
            case INT_IFCMP2_opcode:
                // val1 can't be a constant, val2 must be small enough.
                IfCmp2.setVal1(s, asRegInt(IfCmp2.getClearVal1(s), s, ir));
                IfCmp2.setVal2(s, asImmediateOrRegInt(IfCmp2.getClearVal2(s), s, ir, true));
                break;
            case BOOLEAN_CMP_INT_opcode:
            case BOOLEAN_CMP_ADDR_opcode:
                // val2 must be small enough.
                BooleanCmp.setVal2(s, asImmediateOrRegPolymorphic(BooleanCmp.getClearVal2(s), s, ir, !BooleanCmp.getCond(s).isUNSIGNED()));
                break;
            case LONG_CMP_opcode:
                Binary.setVal1(s, asRegPolymorphic(Binary.getVal1(s), s, ir));
                Binary.setVal2(s, asRegPolymorphic(Binary.getVal2(s), s, ir));
                break;
            case LONG_ADD_opcode:
                if (VM.BuildFor64Addr) {
                    s.changeOperatorTo(REF_ADD);
                    Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, true));
                }
                break;
            case INT_ADD_opcode:
                s.changeOperatorTo(REF_ADD);
                Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, true));
                break;
            case REF_ADD_opcode:
                Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, true));
                break;
            case LONG_SUB_opcode:
                if (VM.BuildFor64Addr) {
                    s.changeOperatorTo(REF_SUB);
                    Binary.setVal1(s, asImmediateOrRegPolymorphic(Binary.getClearVal1(s), s, ir, true));
                // val2 isn't be constant (if it were, Simplifier would have
                // converted this into an ADD of -Val2).
                }
                break;
            case INT_SUB_opcode:
                s.changeOperatorTo(REF_SUB);
                Binary.setVal1(s, asImmediateOrRegPolymorphic(Binary.getClearVal1(s), s, ir, true));
                // converted this into an ADD of -Val2).
                break;
            case REF_SUB_opcode:
                Binary.setVal1(s, asImmediateOrRegPolymorphic(Binary.getClearVal1(s), s, ir, true));
                // converted this into an ADD of -Val2).
                break;
            case INT_MUL_opcode:
                Binary.setVal2(s, asImmediateOrRegInt(Binary.getClearVal2(s), s, ir, true));
                break;
            case LONG_MUL_opcode:
                if (VM.BuildFor64Addr) {
                    Binary.setVal2(s, asImmediateOrRegLong(Binary.getClearVal2(s), s, ir, true));
                }
                break;
            // seem to expect constant operands at all.
            case INT_REM_opcode:
            case INT_DIV_opcode:
                GuardedBinary.setVal1(s, asRegInt(GuardedBinary.getClearVal1(s), s, ir));
                GuardedBinary.setVal2(s, asRegInt(GuardedBinary.getClearVal2(s), s, ir));
                break;
            case LONG_REM_opcode:
            case LONG_DIV_opcode:
                if (VM.BuildFor64Addr) {
                    GuardedBinary.setVal1(s, asRegLong(GuardedBinary.getClearVal1(s), s, ir));
                    GuardedBinary.setVal2(s, asRegLong(GuardedBinary.getClearVal2(s), s, ir));
                }
                break;
            case LONG_NEG_opcode:
                if (VM.BuildFor64Addr) {
                    s.changeOperatorTo(REF_NEG);
                }
                break;
            case INT_NEG_opcode:
                s.changeOperatorTo(REF_NEG);
                break;
            case LONG_NOT_opcode:
                if (VM.BuildFor64Addr) {
                    s.changeOperatorTo(REF_NOT);
                }
                break;
            case INT_NOT_opcode:
                s.changeOperatorTo(REF_NOT);
                break;
            case LONG_AND_opcode:
                if (VM.BuildFor64Addr) {
                    s.changeOperatorTo(REF_AND);
                    // unsigned immediate
                    Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
                }
                break;
            case INT_AND_opcode:
                s.changeOperatorTo(REF_AND);
                // unsigned immediate
                Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
                break;
            case REF_AND_opcode:
                // unsigned immediate
                Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
                break;
            case LONG_OR_opcode:
                if (VM.BuildFor64Addr) {
                    s.changeOperatorTo(REF_OR);
                    // unsigned immediate
                    Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
                }
                break;
            case INT_OR_opcode:
                s.changeOperatorTo(REF_OR);
                // unsigned immediate
                Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
                break;
            case REF_OR_opcode:
                // unsigned immediate
                Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
                break;
            case LONG_XOR_opcode:
                if (VM.BuildFor64Addr) {
                    s.changeOperatorTo(REF_XOR);
                    // unsigned immediate
                    Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
                }
                break;
            case INT_XOR_opcode:
                s.changeOperatorTo(REF_XOR);
                // unsigned immediate
                Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
                break;
            case REF_XOR_opcode:
                // unsigned immediate
                Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
                break;
            case REF_SHL_opcode:
                s.changeOperatorTo(VM.BuildFor32Addr ? INT_SHL : LONG_SHL);
                // Val2 could be a constant, but Val1 apparently can't be.
                Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
                break;
            case LONG_SHL_opcode:
                if (VM.BuildFor64Addr) {
                    // Val2 could be a constant, but Val1 apparently can't be.
                    Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
                }
                break;
            case INT_SHL_opcode:
                // Val2 could be a constant, but Val1 apparently can't be.
                Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
                break;
            case REF_SHR_opcode:
                s.changeOperatorTo(VM.BuildFor32Addr ? INT_SHR : LONG_SHR);
                // Val2 could be a constant, but Val1 apparently can't be.
                Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
                break;
            case LONG_SHR_opcode:
                if (VM.BuildFor64Addr) {
                    // Val2 could be a constant, but Val1 apparently can't be.
                    Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
                }
                break;
            case INT_SHR_opcode:
                // Val2 could be a constant, but Val1 apparently can't be.
                Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
                break;
            case REF_USHR_opcode:
                s.changeOperatorTo(VM.BuildFor32Addr ? INT_USHR : LONG_USHR);
                // Val2 could be a constant, but Val1 apparently can't be.
                Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
                break;
            case LONG_USHR_opcode:
                if (VM.BuildFor64Addr) {
                    // Val2 could be a constant, but Val1 apparently can't be.
                    Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
                }
                break;
            case INT_USHR_opcode:
                // Val2 could be a constant, but Val1 apparently can't be.
                Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
                break;
            // Deal with Simplifier.CF_FLOAT or Simplifier.CF_DOUBLE being false
            case INT_2DOUBLE_opcode:
            case INT_2FLOAT_opcode:
            case INT_BITS_AS_FLOAT_opcode:
                Unary.setVal(s, asRegInt(Unary.getVal(s), s, ir));
                break;
            case ADDR_2INT_opcode:
                s.changeOperatorTo(VM.BuildFor32Addr ? REF_MOVE : LONG_2INT);
                break;
            case ADDR_2LONG_opcode:
                s.changeOperatorTo(VM.BuildFor32Addr ? INT_2LONG : REF_MOVE);
                break;
            case INT_2ADDRSigExt_opcode:
                s.changeOperatorTo(VM.BuildFor32Addr ? REF_MOVE : INT_2LONG);
                break;
            case INT_2ADDRZerExt_opcode:
                if (VM.BuildFor32Addr) {
                    s.changeOperatorTo(REF_MOVE);
                }
                break;
            case LONG_2ADDR_opcode:
                s.changeOperatorTo(VM.BuildFor64Addr ? REF_MOVE : LONG_2INT);
                break;
            case NULL_CHECK_opcode:
                NullCheck.setRef(s, asRegAddress(NullCheck.getClearRef(s), s, ir));
                break;
            // Force all call parameters to be in registers
            case SYSCALL_opcode:
            case CALL_opcode:
                {
                    int numArgs = Call.getNumberOfParams(s);
                    for (int i = 0; i < numArgs; i++) {
                        Call.setParam(s, i, asRegPolymorphic(Call.getClearParam(s, i), s, ir));
                    }
                }
                break;
            case RETURN_opcode:
                if (Return.hasVal(s)) {
                    Return.setVal(s, asRegPolymorphic(Return.getClearVal(s), s, ir));
                }
                break;
        }
    }
}
Also used : LongConstantOperand(org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand) StringConstantOperand(org.jikesrvm.compilers.opt.ir.operand.StringConstantOperand) LongConstantOperand(org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand) DoubleConstantOperand(org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) CodeConstantOperand(org.jikesrvm.compilers.opt.ir.operand.CodeConstantOperand) NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) FloatConstantOperand(org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand) TIBConstantOperand(org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) ClassConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ClassConstantOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) ObjectConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand) StringConstantOperand(org.jikesrvm.compilers.opt.ir.operand.StringConstantOperand) ConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ConstantOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) Offset(org.vmmagic.unboxed.Offset) NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) ClassConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ClassConstantOperand) DoubleConstantOperand(org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand) ObjectConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand) FloatConstantOperand(org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand) TIBConstantOperand(org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException) CodeConstantOperand(org.jikesrvm.compilers.opt.ir.operand.CodeConstantOperand)

Example 33 with Instruction

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

the class LiveAnalysis method getLiveRegistersOnEntry.

/**
 * @param bb the basic block we're interested in
 * @return the set of registers that are live across a basic block, and who
 * are live before the basic block entry.
 */
HashSet<Register> getLiveRegistersOnEntry(BasicBlock bb) {
    HashSet<Register> result = new HashSet<Register>(10);
    for (Enumeration<LiveIntervalElement> e = liveIntervals.enumerateLiveIntervals(bb); e.hasMoreElements(); ) {
        LiveIntervalElement lie = e.nextElement();
        Instruction begin = lie.getBegin();
        if (begin == null)
            result.add(lie.getRegister());
    }
    return result;
}
Also used : Register(org.jikesrvm.compilers.opt.ir.Register) LiveIntervalElement(org.jikesrvm.compilers.opt.regalloc.LiveIntervalElement) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) HashSet(java.util.HashSet)

Example 34 with Instruction

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

the class LiveAnalysis method getLiveRegistersOnExit.

/**
 * @param bb the basic block we're interested in
 * @return the set of registers that are live across a basic block, and who
 * are live after the basic block exit.
 */
HashSet<Register> getLiveRegistersOnExit(BasicBlock bb) {
    HashSet<Register> result = new HashSet<Register>(10);
    for (Enumeration<LiveIntervalElement> e = liveIntervals.enumerateLiveIntervals(bb); e.hasMoreElements(); ) {
        LiveIntervalElement lie = e.nextElement();
        Instruction end = lie.getEnd();
        if (end == null)
            result.add(lie.getRegister());
    }
    return result;
}
Also used : Register(org.jikesrvm.compilers.opt.ir.Register) LiveIntervalElement(org.jikesrvm.compilers.opt.regalloc.LiveIntervalElement) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) HashSet(java.util.HashSet)

Example 35 with Instruction

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

the class LiveAnalysis method computeBlockGenAndKill.

/**
 * Compute summary (local) live variable analysis for a basic block, which
 * is basically Gen and Kill information.<p>
 *
 * For more details, see the paper "Efficient and Precise Modeling of
 * Exceptions for the Analysis of Java Programs" by Choi, Grove, Hind
 * and Sarkar in ACM PASTE99 workshop.
 *
 * @param bblock the basic block
 * @param ir the governing IR
 */
private void computeBlockGenAndKill(BasicBlock bblock, IR ir) {
    if (VERBOSE) {
        System.out.println(" --> Computing Gen/Kill for block " + bblock);
    }
    // Tells whether we've seen the first PEI
    boolean seenFirstPEI = false;
    // Because control flow may emanate from a potentially excepting
    // instruction (PEI) out of the basic block, care must be taken
    // when computing what can be killed by a basic block.
    // 
    // S1:  y =
    // S2:  <exception-raising inst>
    // S3:  x =
    // For example in the block above, live variables coming from
    // the normal exit of the block (i.e., after S3) can be killed
    // by S1 or S3 (depending on the variable).  However, live variables
    // coming from the PEI edge (at S2) can only be killed by S1.
    // Thus, when a block contains PEIs, we need to distinguish the
    // kill sets.  Namely, we need
    // Kill_tot  -  what can be killed anywhere in the block
    // Kill_n    -  what can be killed from PEI_n on up
    // Kill_n-1  -  what can be killed from PEI_n-1 on up
    // ...
    // Kill_1    -  what can be killed from PEI_1 on up
    // We would then compute In as follows
    // 
    // In = Out_norm - Kill_tot   (all vars entering from bottom are eligible
    // to be killed)
    // U Out_n - Kill_n
    // U Out_n-1 - Kill_n-1
    // ...
    // U Out_1 - Kill_1
    // U Gen
    // where Out_n is the out information at PEI i, i.e., the IN information
    // for whatever handlers may catch PEI i
    // ...
    // PEI 1
    // ...
    // PEI n-1
    // ...
    // PEI n
    // ...
    // If we conservatively assume all handlers for the block of interest
    // can be reached by all PEIs in this block then the equation becomes
    // In = (Out_norm - Kill_tot)
    // U (Out_hand - Kill_n)
    // U (Out_hand - Kill_n-1)
    // ...
    // U (Out_hand - Kill_1)
    // U Gen
    // where "Out_hand" is the union of the in sets for all handlers.
    // Since Kill_i is a subset of Kill_j, for i < j, we can simplify to
    // In = (Out_norm - Kill_tot)
    // U (Out_hand - Kill_1)    (1)
    // U Gen
    // Since kill_1 is a subset of kill_tot, we don't need the
    // the parenthesis (and the intermediate set)
    // If there are no handlers than (1) is empty and we don't need
    // to compute Kill_1.  We will take this approach for now.
    // So for each block we will have at most 2 kill sets: Kill_tot and Kill_1
    // This code finds the first PEI in the block
    Instruction firstPEI = null;
    if (bblock.canThrowExceptions()) {
        for (Instruction inst = bblock.firstInstruction(); inst != bblock.lastInstruction(); inst = inst.nextInstructionInCodeOrder()) {
            if (inst.isPEI() && bblock.getApplicableExceptionalOut(inst).hasMoreElements()) {
                firstPEI = inst;
                // remember that this block has a PEI with a handler for use
                // later in "processBlock"
                bbLiveInfo[bblock.getNumber()].setContainsPEIWithHandler(true);
                break;
            }
        }
    }
    // Get any uses from PHIs, which are in the successor blocks
    getUsesFromPhis(bblock);
    // Traverse instructions in reverse order within the basic block.
    for (Instruction inst = bblock.lastInstruction(); inst != bblock.firstInstruction(); inst = inst.prevInstructionInCodeOrder()) {
        // traverse from defs to uses becauses uses happen after
        // (in a backward sense) defs
        Enumeration<Operand> defs = inst.getPureDefs();
        while (defs.hasMoreElements()) {
            Operand def = defs.nextElement();
            if (def instanceof RegisterOperand) {
                RegisterOperand regOp = (RegisterOperand) def;
                // Do we care about this reg?
                if (isSkippableReg(regOp, ir)) {
                    continue;
                }
                TypeReference regType = regOp.getType();
                // include it.  It will be picked up later by local propagation phase.
                if (regOp.getRegister().spansBasicBlock() && regType != null) {
                    // if it is a DEF we place it is the BBKillSet and remove it from
                    // the GEN set, (GEN should only contain upward-exposed uses,
                    // i.e., uses that are NOT dominated by a DEF).
                    // We don't need to worry about PEIs here because
                    // later instructions (traversing backwards like we are)
                    // will always dominate earlier instructions *of this block*
                    bbLiveInfo[bblock.getNumber()].BBKillSet().add(regOp);
                    bbLiveInfo[bblock.getNumber()].getGen().remove(regOp);
                    // If there are no PEIs in this block we don't bother to add
                    if (seenFirstPEI) {
                        bbLiveInfo[bblock.getNumber()].firstPEIKillSet().add(regOp);
                    }
                }
            }
        }
        // Now process the uses, unless this is a PHI operator
        if (inst.operator() != PHI) {
            for (Enumeration<Operand> uses = inst.getUses(); uses.hasMoreElements(); ) {
                Operand use = uses.nextElement();
                if (use instanceof RegisterOperand) {
                    RegisterOperand regOp = (RegisterOperand) use;
                    // Do we care about this reg?
                    if (isSkippableReg(regOp, ir)) {
                        continue;
                    }
                    TypeReference regType = regOp.getType();
                    // later by local propagation phase.
                    if (regOp.getRegister().spansBasicBlock() && regType != null) {
                        bbLiveInfo[bblock.getNumber()].getGen().add(regOp);
                    }
                }
            // is RegOp
            }
        // foreach use
        }
        // If so, set the flag so we can start killing.
        if (firstPEI == inst) {
            seenFirstPEI = true;
        }
    }
    // foreach instruction in block
    if (VERBOSE) {
        System.out.println("  Gen: " + bbLiveInfo[bblock.getNumber()].getGen());
        System.out.println("  Kill: " + bbLiveInfo[bblock.getNumber()].BBKillSet());
        System.out.println("  1st PEI Kill: " + bbLiveInfo[bblock.getNumber()].firstPEIKillSet());
        System.out.println(" ---> Done computing Gen/Kill for block");
    }
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) InlinedOsrTypeInfoOperand(org.jikesrvm.compilers.opt.ir.operand.InlinedOsrTypeInfoOperand) BasicBlockOperand(org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) TypeReference(org.jikesrvm.classloader.TypeReference) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Aggregations

Instruction (org.jikesrvm.compilers.opt.ir.Instruction)356 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)204 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)144 BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)117 Register (org.jikesrvm.compilers.opt.ir.Register)106 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)72 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)61 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)61 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)54 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)53 Test (org.junit.Test)49 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)46 TypeReference (org.jikesrvm.classloader.TypeReference)38 BranchOperand (org.jikesrvm.compilers.opt.ir.operand.BranchOperand)38 NullConstantOperand (org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand)35 BasicBlockOperand (org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand)33 HeapOperand (org.jikesrvm.compilers.opt.ir.operand.HeapOperand)33 TrapCodeOperand (org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand)31 AddressConstantOperand (org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand)28 TypeOperand (org.jikesrvm.compilers.opt.ir.operand.TypeOperand)27