Search in sources :

Example 1 with NullConstantOperand

use of org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand 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 2 with NullConstantOperand

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

the class LoopVersioning method generateNullCheckBranchBlocks.

/**
 * Generate null check branch blocks
 *
 * @param loop the current loop where checks are being eliminated
 * @param checksToEliminate all of the checks that are being eliminated in the pass
 * @param optimalRegMap a map from original register to the register used in the optimal loop
 * @param block the block to generate code into
 * @param unoptimizedLoopEntry entry to the unoptimized loop for if the check fails
 * @return the new block to generate code into
 */
private BasicBlock generateNullCheckBranchBlocks(AnnotatedLSTNode loop, ArrayList<Instruction> checksToEliminate, HashMap<Register, Register> optimalRegMap, BasicBlock block, BasicBlock unoptimizedLoopEntry) {
    // Map of already generated null check references to their
    // corresponding guard result
    HashMap<Register, Operand> refToGuardMap = new HashMap<Register, Operand>();
    // Iterate over checks
    for (Instruction instr : checksToEliminate) {
        // Is this a null check
        if (NullCheck.conforms(instr)) {
            // the generated branch instruction
            Instruction branch;
            // the reference to compare
            Operand ref = AnnotatedLSTNode.follow(NullCheck.getRef(instr));
            // the guard result to define
            RegisterOperand guardResult = NullCheck.getGuardResult(instr).copyRO();
            guardResult.setRegister(optimalRegMap.get(guardResult.getRegister()));
            // check if we've generated this test already
            if (ref.isRegister() && refToGuardMap.containsKey(ref.asRegister().getRegister())) {
                // yes - generate just a guard move
                branch = Move.create(GUARD_MOVE, guardResult, refToGuardMap.get(ref.asRegister().getRegister()).copy());
                branch.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
                block.appendInstruction(branch);
            } else {
                // check if we can just move a guard from the loop predecessors
                RegisterOperand guard = nullCheckPerformedInLoopPredecessors(loop.header, instr);
                if (guard != null) {
                    // yes - generate just a guard move
                    branch = Move.create(GUARD_MOVE, guardResult, guard.copyRO());
                    branch.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
                    block.appendInstruction(branch);
                } else {
                    // generate explicit null test
                    branch = IfCmp.create(REF_IFCMP, guardResult, ref.copy(), new NullConstantOperand(), ConditionOperand.EQUAL(), unoptimizedLoopEntry.makeJumpTarget(), BranchProfileOperand.unlikely());
                    if (ref.isRegister()) {
                        refToGuardMap.put(ref.asRegister().getRegister(), guardResult);
                    }
                    branch.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
                    block.appendInstruction(branch);
                    // Adjust block
                    block.insertOut(unoptimizedLoopEntry);
                    BasicBlock new_block = block.createSubBlock(SYNTH_LOOP_VERSIONING_BCI, ir);
                    BasicBlock temp = (BasicBlock) block.next;
                    ir.cfg.breakCodeOrder(block, temp);
                    ir.cfg.linkInCodeOrder(block, new_block);
                    ir.cfg.linkInCodeOrder(new_block, temp);
                    block.insertOut(new_block);
                    block = new_block;
                }
            }
        }
    }
    return block;
}
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) HashMap(java.util.HashMap) 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) NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) HeapOperand(org.jikesrvm.compilers.opt.ir.operand.HeapOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Example 3 with NullConstantOperand

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

the class DynamicTypeCheckExpansion method instanceOf.

/**
 * Expand an instanceof instruction into the LIR sequence that implements
 * the dynamic type check.  Ref may contain a null ptr at runtime.
 *
 * @param s an INSTANCEOF or INSTANCEOF_UNRESOLVED instruction to expand
 * @param ir the enclosing IR
 * @return the last Instruction in the generated LIR sequence.
 */
static Instruction instanceOf(Instruction s, IR ir) {
    RegisterOperand result = InstanceOf.getClearResult(s);
    TypeReference LHStype = InstanceOf.getType(s).getTypeRef();
    Operand ref = InstanceOf.getClearRef(s);
    Instruction next = s.nextInstructionInCodeOrder();
    if (next.operator() == INT_IFCMP && IfCmp.getVal1(next) instanceof RegisterOperand && result.similar(IfCmp.getVal1(next))) {
        // The result of instanceof is being consumed by a conditional branch.
        // Optimize this case by generating a branching type check
        // instead of producing a value.
        // TODO: This is really not safe: suppose the if is NOT the
        // only use of the result of the instanceof.
        // The way to fix this is to add ifInstanceOf and ifNotInstanceOf
        // operators to the IR and have Simple transform
        // instanceof, intIfCmp based on the U/D chains.
        // See defect 2114.
        Operand val2 = IfCmp.getVal2(next);
        if (VM.VerifyAssertions)
            VM._assert(val2.isIntConstant());
        int ival2 = ((IntConstantOperand) val2).value;
        ConditionOperand cond = IfCmp.getCond(next);
        boolean branchCondition = (((ival2 == 0) && (cond.isNOT_EQUAL() || cond.isLESS_EQUAL())) || ((ival2 == 1) && (cond.isEQUAL() || cond.isGREATER_EQUAL())));
        BasicBlock branchBB = next.getBranchTarget();
        RegisterOperand oldGuard = IfCmp.getGuardResult(next);
        next.remove();
        BasicBlock fallThroughBB = fallThroughBB(s, ir);
        BasicBlock falseBranch = branchCondition ? fallThroughBB : branchBB;
        BasicBlock trueBranch = branchCondition ? branchBB : fallThroughBB;
        BranchProfileOperand bp = IfCmp.getClearBranchProfile(next);
        if (branchCondition)
            bp = bp.flip();
        Instruction nullComp = IfCmp.create(REF_IFCMP, oldGuard.copyRO(), ref.copy(), new NullConstantOperand(), ConditionOperand.EQUAL(), falseBranch.makeJumpTarget(), BranchProfileOperand.unlikely());
        s.insertBefore(nullComp);
        BasicBlock myBlock = s.getBasicBlock();
        BasicBlock instanceOfBlock = myBlock.splitNodeAt(nullComp, ir);
        myBlock.insertOut(instanceOfBlock);
        myBlock.insertOut(falseBranch);
        ir.cfg.linkInCodeOrder(myBlock, instanceOfBlock);
        Operand RHStib = getTIB(s, ir, ref, oldGuard.copyRO());
        return generateBranchingTypeCheck(s, ir, ref.copy(), LHStype, RHStib, trueBranch, falseBranch, oldGuard.copy().asRegister(), bp);
    } else {
        // Not a branching pattern
        RegisterOperand guard = ir.regpool.makeTempValidation();
        BasicBlock instanceOfBlock = s.getBasicBlock().segregateInstruction(s, ir);
        BasicBlock prevBB = instanceOfBlock.prevBasicBlockInCodeOrder();
        BasicBlock nextBB = instanceOfBlock.nextBasicBlockInCodeOrder();
        BasicBlock nullCaseBB = instanceOfBlock.createSubBlock(s.getBytecodeIndex(), ir, .01f);
        prevBB.appendInstruction(IfCmp.create(REF_IFCMP, guard, ref.copy(), new NullConstantOperand(), ConditionOperand.EQUAL(), nullCaseBB.makeJumpTarget(), BranchProfileOperand.unlikely()));
        nullCaseBB.appendInstruction(Move.create(INT_MOVE, result.copyD2D(), IC(0)));
        nullCaseBB.appendInstruction(Goto.create(GOTO, nextBB.makeJumpTarget()));
        // Stitch together the CFG; add nullCaseBB to the end of code array.
        prevBB.insertOut(nullCaseBB);
        nullCaseBB.insertOut(nextBB);
        ir.cfg.addLastInCodeOrder(nullCaseBB);
        Operand RHStib = getTIB(s, ir, ref, guard.copyD2U());
        return generateValueProducingTypeCheck(s, ir, ref.copy(), LHStype, RHStib, result);
    }
}
Also used : NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) TrapCodeOperand(org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) TypeReference(org.jikesrvm.classloader.TypeReference) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Example 4 with NullConstantOperand

use of org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand 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 5 with NullConstantOperand

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

the class Simplifier method refLoad.

private static DefUseEffect refLoad(Instruction s, OptOptions opts) {
    if (opts.SIMPLIFY_TIB_OPS) {
        Operand base = Load.getAddress(s);
        if (base.isTIBConstant()) {
            TIBConstantOperand tib = base.asTIBConstant();
            Operand offset = Load.getOffset(s);
            if (tib.value.isInstantiated() && offset.isConstant()) {
                // Reading from a fixed offset from an effectively
                // constant array
                int intOffset;
                if (offset.isIntConstant()) {
                    intOffset = offset.asIntConstant().value;
                } else {
                    intOffset = offset.asAddressConstant().value.toInt();
                }
                int intSlot = intOffset >> LOG_BYTES_IN_ADDRESS;
                // Create appropriate constant operand for TIB slot
                ConstantOperand result;
                TIB tibArray = tib.value.getTypeInformationBlock();
                if (tibArray.slotContainsTib(intSlot)) {
                    RVMType typeOfTIB = ((TIB) tibArray.get(intSlot)).getType();
                    result = new TIBConstantOperand(typeOfTIB);
                } else if (tibArray.slotContainsCode(intSlot)) {
                    // some virtual calls go via the JTOC
                    if (opts.H2L_CALL_VIA_JTOC) {
                        RVMMethod method = tib.value.getTIBMethodAtSlot(intSlot);
                        result = new CodeConstantOperand(method);
                    } else {
                        return DefUseEffect.UNCHANGED;
                    }
                } else {
                    if (tibArray.get(intSlot) == null) {
                        result = new NullConstantOperand();
                    } else {
                        result = new ObjectConstantOperand(tibArray.get(intSlot), Offset.zero());
                    }
                }
                Move.mutate(s, REF_MOVE, Load.getClearResult(s), result);
                return DefUseEffect.MOVE_FOLDED;
            }
        }
    }
    return DefUseEffect.UNCHANGED;
}
Also used : LongConstantOperand(org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand) CodeConstantOperand(org.jikesrvm.compilers.opt.ir.operand.CodeConstantOperand) ObjectConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand) NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) TIBConstantOperand(org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) ConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ConstantOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) RVMMethod(org.jikesrvm.classloader.RVMMethod) NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) UnreachableOperand(org.jikesrvm.compilers.opt.ir.operand.UnreachableOperand) LongConstantOperand(org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand) TypeOperand(org.jikesrvm.compilers.opt.ir.operand.TypeOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) CodeConstantOperand(org.jikesrvm.compilers.opt.ir.operand.CodeConstantOperand) ObjectConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand) NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) TIBConstantOperand(org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand) TrapCodeOperand(org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) ConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ConstantOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) TIBConstantOperand(org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand) RVMType(org.jikesrvm.classloader.RVMType) ObjectConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand) TIB(org.jikesrvm.objectmodel.TIB) CodeConstantOperand(org.jikesrvm.compilers.opt.ir.operand.CodeConstantOperand)

Aggregations

NullConstantOperand (org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand)13 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)12 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)11 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)10 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)9 AddressConstantOperand (org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand)8 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)8 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)8 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)8 LongConstantOperand (org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand)8 DoubleConstantOperand (org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand)7 FloatConstantOperand (org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand)7 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)7 TrapCodeOperand (org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand)7 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)7 TypeReference (org.jikesrvm.classloader.TypeReference)6 BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)6 ConstantOperand (org.jikesrvm.compilers.opt.ir.operand.ConstantOperand)5 ObjectConstantOperand (org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand)5 RVMType (org.jikesrvm.classloader.RVMType)4