Search in sources :

Example 11 with BranchProfileOperand

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

the class DynamicTypeCheckExpansion method generateBranchingTypeCheck.

/**
 * Generate a branching dynamic type check.
 * This routine assumes that the CFG and code order are already
 * correctly established.
 * This routine must either remove s or mutate it.
 *
 * @param s          The Instruction that is to be replaced by a
 *                   branching type check
 * @param ir         The IR containing the instruction to be expanded.
 * @param RHSobj     The RegisterOperand containing the rhs object.
 * @param LHStype    The TypeReference to be tested against.
 * @param RHStib     The Operand containing the TIB of the rhs.
 * @param trueBlock  The BasicBlock to continue at if the typecheck
 *                   evaluates to true
 * @param falseBlock The BasicBlock to continue at if the typecheck
 *                   evaluates to false.
 * @param oldGuard   A suitable guard operand (not necessarily related
 *                   the instruction that is to be replaced).
 * @param falseProb   The probability that typecheck will branch to the falseBlock
 * @return the opt instruction immediately before the instruction to
 *         continue expansion.
 */
private static Instruction generateBranchingTypeCheck(Instruction s, IR ir, Operand RHSobj, TypeReference LHStype, Operand RHStib, BasicBlock trueBlock, BasicBlock falseBlock, RegisterOperand oldGuard, BranchProfileOperand falseProb) {
    Instruction continueAt = Goto.create(GOTO, trueBlock.makeJumpTarget());
    continueAt.copyPosition(s);
    s.insertBefore(continueAt);
    s.remove();
    if (LHStype.isClassType()) {
        RVMClass LHSclass = (RVMClass) LHStype.peekType();
        if (LHSclass != null && LHSclass.isResolved()) {
            // class or interface
            if (LHSclass.isInterface()) {
                // A resolved interface (case 4)
                int interfaceIndex = LHSclass.getDoesImplementIndex();
                int interfaceMask = LHSclass.getDoesImplementBitMask();
                RegisterOperand doesImpl = InsertUnary(continueAt, ir, GET_DOES_IMPLEMENT_FROM_TIB, TypeReference.IntArray, RHStib);
                if (DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {
                    RegisterOperand doesImplLength = InsertGuardedUnary(continueAt, ir, ARRAYLENGTH, TypeReference.Int, doesImpl.copyD2U(), TG());
                    Instruction lengthCheck = IfCmp.create(INT_IFCMP, oldGuard, doesImplLength, IC(interfaceIndex), ConditionOperand.LESS_EQUAL(), falseBlock.makeJumpTarget(), BranchProfileOperand.unlikely());
                    if (oldGuard != null) {
                        oldGuard = oldGuard.copyD2D();
                    }
                    continueAt.insertBefore(lengthCheck);
                    BasicBlock oldBlock = continueAt.getBasicBlock();
                    oldBlock.splitNodeWithLinksAt(lengthCheck, ir);
                    // required due to splitNode!
                    oldBlock.insertOut(falseBlock);
                }
                RegisterOperand entry = InsertLoadOffset(continueAt, ir, INT_LOAD, TypeReference.Int, doesImpl, Offset.fromIntZeroExtend(interfaceIndex << 2), new LocationOperand(TypeReference.Int), TG());
                RegisterOperand bit = insertBinary(continueAt, ir, INT_AND, TypeReference.Int, entry, IC(interfaceMask));
                continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, bit, IC(0), ConditionOperand.EQUAL(), falseBlock.makeJumpTarget(), falseProb));
                return continueAt;
            } else {
                // A resolved class (cases 5 and 6 in DynamicTypeCheck)
                if (LHSclass.isFinal()) {
                    // For a final class, we can do a PTR compare of
                    // rhsTIB and the TIB of the class
                    Operand classTIB = getTIB(continueAt, ir, LHSclass);
                    continueAt.insertBefore(IfCmp.create(REF_IFCMP, oldGuard, RHStib, classTIB, ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
                    return continueAt;
                } else {
                    // Do the full blown case 5 or 6 typecheck.
                    int LHSDepth = LHSclass.getTypeDepth();
                    int LHSId = LHSclass.getId();
                    RegisterOperand superclassIds = InsertUnary(continueAt, ir, GET_SUPERCLASS_IDS_FROM_TIB, TypeReference.ShortArray, RHStib);
                    if (DynamicTypeCheck.MIN_SUPERCLASS_IDS_SIZE <= LHSDepth) {
                        RegisterOperand superclassIdsLength = InsertGuardedUnary(continueAt, ir, ARRAYLENGTH, TypeReference.Int, superclassIds.copyD2U(), TG());
                        Instruction lengthCheck = IfCmp.create(INT_IFCMP, oldGuard, superclassIdsLength, IC(LHSDepth), ConditionOperand.LESS(), falseBlock.makeJumpTarget(), BranchProfileOperand.unlikely());
                        if (oldGuard != null) {
                            oldGuard = oldGuard.copyD2D();
                        }
                        continueAt.insertBefore(lengthCheck);
                        BasicBlock oldBlock = continueAt.getBasicBlock();
                        oldBlock.splitNodeWithLinksAt(lengthCheck, ir);
                        // required due to splitNode!
                        oldBlock.insertOut(falseBlock);
                    }
                    RegisterOperand refCandidate = InsertLoadOffset(continueAt, ir, USHORT_LOAD, TypeReference.Short, superclassIds, Offset.fromIntZeroExtend(LHSDepth << 1), new LocationOperand(TypeReference.Short), TG());
                    continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, refCandidate, IC(LHSId), ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
                    return continueAt;
                }
            }
        } else {
            // A non-resolved class or interface. Case 3 of DynamicTypeCheck
            // Branch on the result of a call to
            // RuntimeEntrypoints.instance
            RegisterOperand result = ir.regpool.makeTempInt();
            RVMMethod target = Entrypoints.instanceOfMethod;
            Instruction call = Call.create2(CALL, result, AC(target.getOffset()), MethodOperand.STATIC(target), RHSobj, IC(LHStype.getId()));
            call.copyPosition(continueAt);
            continueAt.insertBefore(call);
            call = callHelper(call, ir);
            continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, result.copyD2U(), IC(0), ConditionOperand.EQUAL(), falseBlock.makeJumpTarget(), falseProb));
            return continueAt;
        }
    }
    if (LHStype.isArrayType()) {
        // Case 2 of DynamicTypeCheck: LHS is an array.
        RVMArray LHSArray = (RVMArray) LHStype.peekType();
        if (LHSArray != null) {
            Operand classTIB = getTIB(continueAt, ir, LHSArray);
            RVMType innermostElementType = LHSArray.getInnermostElementType();
            if (innermostElementType.isPrimitiveType() || innermostElementType.isUnboxedType() || (innermostElementType.asClass().isResolved() && innermostElementType.asClass().isFinal())) {
                // [^k of primitive or [^k of final class. Just like final classes,
                // a PTR compare of rhsTIB and the TIB of the class gives the answer.
                continueAt.insertBefore(IfCmp.create(REF_IFCMP, oldGuard, RHStib, classTIB, ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
                return continueAt;
            }
            // TODO: branch probability calculation is somewhat bogus for this case.
            Instruction shortcircuit = IfCmp.create(REF_IFCMP, oldGuard, RHStib, classTIB, ConditionOperand.EQUAL(), trueBlock.makeJumpTarget(), new BranchProfileOperand());
            if (oldGuard != null) {
                oldGuard = oldGuard.copyD2D();
            }
            continueAt.insertBefore(shortcircuit);
            BasicBlock myBlock = shortcircuit.getBasicBlock();
            BasicBlock mainBlock = myBlock.splitNodeWithLinksAt(shortcircuit, ir);
            // must come after the splitNodeAt
            myBlock.insertOut(trueBlock);
            RegisterOperand rhsType = InsertUnary(continueAt, ir, GET_TYPE_FROM_TIB, TypeReference.Type, RHStib.copy());
            if (innermostElementType.isJavaLangObjectType()) {
                IntConstantOperand lhsDimension = IC(LHStype.getDimensionality());
                RegisterOperand rhsDimension = getField(continueAt, ir, rhsType, Entrypoints.dimensionField);
                Instruction dimTest = IfCmp2.create(INT_IFCMP2, oldGuard, rhsDimension, lhsDimension, ConditionOperand.GREATER(), trueBlock.makeJumpTarget(), ((BranchProfileOperand) falseProb.copy()).flip(), ConditionOperand.LESS(), falseBlock.makeJumpTarget(), (BranchProfileOperand) falseProb.copy());
                if (oldGuard != null) {
                    oldGuard = oldGuard.copyD2D();
                }
                continueAt.insertBefore(dimTest);
                // BasicBlock testBlock =
                mainBlock.splitNodeWithLinksAt(dimTest, ir);
                mainBlock.insertOut(trueBlock);
                mainBlock.insertOut(falseBlock);
                RegisterOperand rhsInnermostElementTypeDimension = getField(continueAt, ir, rhsType.copyU2U(), Entrypoints.innermostElementTypeDimensionField);
                continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, rhsInnermostElementTypeDimension, IC(0), ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
                return continueAt;
            }
        }
        // Not a case we want to handle inline
        RVMMethod target = Entrypoints.instanceOfMethod;
        RegisterOperand callResult = ir.regpool.makeTempInt();
        Instruction call = Call.create2(CALL, callResult, AC(target.getOffset()), MethodOperand.STATIC(target), RHSobj, IC(LHStype.getId()));
        call.copyPosition(continueAt);
        continueAt.insertBefore(call);
        call = callHelper(call, ir);
        continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, callResult.copyD2U(), IC(0), ConditionOperand.EQUAL(), falseBlock.makeJumpTarget(), falseProb));
        return continueAt;
    }
    OptimizingCompilerException.UNREACHABLE();
    return null;
}
Also used : RVMMethod(org.jikesrvm.classloader.RVMMethod) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) 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) RVMArray(org.jikesrvm.classloader.RVMArray) RVMType(org.jikesrvm.classloader.RVMType) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) RVMClass(org.jikesrvm.classloader.RVMClass)

Example 12 with BranchProfileOperand

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

the class GenerationContext method getConditionalBranchProfileOperand.

// /////////
// Profile data
// /////////
BranchProfileOperand getConditionalBranchProfileOperand(int bcIndex, boolean backwards) {
    float prob;
    BranchProfile bp;
    if (branchProfiles != null && ((bp = branchProfiles.getEntry(bcIndex)) != null)) {
        prob = ((ConditionalBranchProfile) bp).getTakenProbability();
    } else {
        if (branchProfiles != null) {
            VM.sysWrite("Warning: conditional branch profile entry not found");
        }
        if (backwards) {
            prob = 0.9f;
        } else {
            prob = 0.5f;
        }
    }
    // we were completely wrong.
    if (options.inverseFrequencyCounters()) {
        prob = 1f - prob;
    }
    return new BranchProfileOperand(prob);
}
Also used : BranchProfile(org.jikesrvm.compilers.baseline.BranchProfile) ConditionalBranchProfile(org.jikesrvm.compilers.baseline.ConditionalBranchProfile) SwitchBranchProfile(org.jikesrvm.compilers.baseline.SwitchBranchProfile) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)

Example 13 with BranchProfileOperand

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

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

the class ComplexLIR2MIRExpansion method basic_long_ifcmp.

private static void basic_long_ifcmp(Instruction s, IR ir, ConditionOperand cond, Register xh, Register xl, Operand yh, Operand yl) {
    if (cond.isEQUAL() || cond.isNOT_EQUAL()) {
        RegisterOperand th = ir.regpool.makeTempInt();
        RegisterOperand tl = ir.regpool.makeTempInt();
        // tricky... ((xh^yh)|(xl^yl) == 0) <==> (lhll == rhrl)!!
        s.insertBefore(MIR_Move.create(IA32_MOV, th, new RegisterOperand(xh, TypeReference.Int)));
        s.insertBefore(MIR_BinaryAcc.create(IA32_XOR, th.copyD2D(), yh));
        s.insertBefore(MIR_Move.create(IA32_MOV, tl, new RegisterOperand(xl, TypeReference.Int)));
        s.insertBefore(MIR_BinaryAcc.create(IA32_XOR, tl.copyD2D(), yl));
        s.insertBefore(MIR_BinaryAcc.create(IA32_OR, th.copyD2D(), tl.copyD2U()));
        MIR_CondBranch.mutate(s, IA32_JCC, new IA32ConditionOperand(cond), IfCmp.getTarget(s), IfCmp.getBranchProfile(s));
    } else {
        // Do the naive thing and generate multiple compare/branch implementation.
        IA32ConditionOperand cond1;
        IA32ConditionOperand cond2;
        IA32ConditionOperand cond3;
        if (cond.isLESS()) {
            cond1 = IA32ConditionOperand.LT();
            cond2 = IA32ConditionOperand.GT();
            cond3 = IA32ConditionOperand.LLT();
        } else if (cond.isGREATER()) {
            cond1 = IA32ConditionOperand.GT();
            cond2 = IA32ConditionOperand.LT();
            cond3 = IA32ConditionOperand.LGT();
        } else if (cond.isLESS_EQUAL()) {
            cond1 = IA32ConditionOperand.LT();
            cond2 = IA32ConditionOperand.GT();
            cond3 = IA32ConditionOperand.LLE();
        } else if (cond.isGREATER_EQUAL()) {
            cond1 = IA32ConditionOperand.GT();
            cond2 = IA32ConditionOperand.LT();
            cond3 = IA32ConditionOperand.LGE();
        } else {
            // I don't think we use the unsigned compares for longs,
            // so defer actually implementing them until we find a test case. --dave
            cond1 = cond2 = cond3 = null;
            OptimizingCompilerException.TODO();
        }
        BasicBlock myBlock = s.getBasicBlock();
        BasicBlock test2Block = myBlock.createSubBlock(s.getBytecodeIndex(), ir, 0.25f);
        BasicBlock falseBlock = myBlock.splitNodeAt(s, ir);
        BasicBlock trueBlock = IfCmp.getTarget(s).target.getBasicBlock();
        falseBlock.recomputeNormalOut(ir);
        myBlock.insertOut(test2Block);
        myBlock.insertOut(falseBlock);
        myBlock.insertOut(trueBlock);
        test2Block.insertOut(falseBlock);
        test2Block.insertOut(trueBlock);
        ir.cfg.linkInCodeOrder(myBlock, test2Block);
        ir.cfg.linkInCodeOrder(test2Block, falseBlock);
        s.remove();
        myBlock.appendInstruction(CPOS(s, MIR_Compare.create(IA32_CMP, new RegisterOperand(xh, TypeReference.Int), yh)));
        myBlock.appendInstruction(CPOS(s, MIR_CondBranch2.create(IA32_JCC2, cond1, trueBlock.makeJumpTarget(), new BranchProfileOperand(), cond2, falseBlock.makeJumpTarget(), new BranchProfileOperand())));
        test2Block.appendInstruction(CPOS(s, MIR_Compare.create(IA32_CMP, new RegisterOperand(xl, TypeReference.Int), yl)));
        test2Block.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, cond3, trueBlock.makeJumpTarget(), new BranchProfileOperand())));
    }
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) IA32ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ia32.IA32ConditionOperand)

Example 15 with BranchProfileOperand

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

the class ComplexLIR2MIRExpansion method fp_ifcmp.

// the fcmoi/fcmoip was generated by burs
// we do the rest of the expansion here because in some
// cases we must remove a trailing goto, and we
// can't do that in burs!
private static Instruction fp_ifcmp(Instruction s) {
    Instruction nextInstr = s.nextInstructionInCodeOrder();
    BranchOperand testFailed;
    BasicBlock bb = s.getBasicBlock();
    Instruction lastInstr = bb.lastRealInstruction();
    if (lastInstr.operator() == IA32_JMP) {
        // We're in trouble if there is another instruction between s and lastInstr!
        if (VM.VerifyAssertions)
            VM._assert(s.nextInstructionInCodeOrder() == lastInstr);
        // Set testFailed to target of GOTO
        testFailed = MIR_Branch.getClearTarget(lastInstr);
        nextInstr = lastInstr.nextInstructionInCodeOrder();
        lastInstr.remove();
    } else {
        // Set testFailed to label of next (fallthrough basic block)
        testFailed = bb.nextBasicBlockInCodeOrder().makeJumpTarget();
    }
    // Translate condition operand respecting IA32 FCOMI/COMISS/COMISD
    Instruction fcomi = s.prevInstructionInCodeOrder();
    Operand val1 = MIR_Compare.getVal1(fcomi);
    Operand val2 = MIR_Compare.getVal2(fcomi);
    ConditionOperand c = IfCmp.getCond(s);
    BranchOperand target = IfCmp.getTarget(s).copy().asBranch();
    BranchProfileOperand branchProfile = (BranchProfileOperand) IfCmp.getBranchProfile(s).copy();
    // propagate the original probability to the second condition.
    switch(c.value) {
        // (i.e. UNORDERED is a goto to testFailed)
        case ConditionOperand.CMPL_EQUAL:
            if (VM.VerifyAssertions)
                VM._assert(!c.branchIfUnordered());
            // Check whether val1 and val2 operands are the same
            if (!val1.similar(val2)) {
                s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, IA32ConditionOperand.PE(), // PF == 1
                testFailed, new BranchProfileOperand(0f), IA32ConditionOperand.EQ(), // ZF == 1
                target, branchProfile));
                s.insertBefore(MIR_Branch.create(IA32_JMP, (BranchOperand) (testFailed.copy())));
            } else {
                // As val1 == val2 result of compare must be == or UNORDERED
                s.insertBefore(// PF == 0
                MIR_CondBranch.create(// PF == 0
                IA32_JCC, // PF == 0
                IA32ConditionOperand.PO(), target, branchProfile));
                s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
            }
            break;
        case ConditionOperand.CMPL_GREATER:
            if (VM.VerifyAssertions)
                VM._assert(!c.branchIfUnordered());
            s.insertBefore(// CF == 0 and ZF == 0
            MIR_CondBranch.create(// CF == 0 and ZF == 0
            IA32_JCC, // CF == 0 and ZF == 0
            IA32ConditionOperand.LGT(), target, branchProfile));
            s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
            break;
        case ConditionOperand.CMPG_LESS:
            if (VM.VerifyAssertions)
                VM._assert(!c.branchIfUnordered());
            s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, IA32ConditionOperand.PE(), // PF == 1
            testFailed, new BranchProfileOperand(0f), IA32ConditionOperand.LLT(), // CF == 1
            target, branchProfile));
            s.insertBefore(MIR_Branch.create(IA32_JMP, (BranchOperand) (testFailed.copy())));
            break;
        case ConditionOperand.CMPL_GREATER_EQUAL:
            if (VM.VerifyAssertions)
                VM._assert(!c.branchIfUnordered());
            s.insertBefore(// CF == 0
            MIR_CondBranch.create(// CF == 0
            IA32_JCC, // CF == 0
            IA32ConditionOperand.LGE(), target, branchProfile));
            s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
            break;
        case ConditionOperand.CMPG_LESS_EQUAL:
            s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, IA32ConditionOperand.PE(), // PF == 1
            testFailed, new BranchProfileOperand(0f), IA32ConditionOperand.LGT(), // ZF == 0 and CF == 0
            (BranchOperand) (testFailed.copy()), branchProfile));
            s.insertBefore(MIR_Branch.create(IA32_JMP, target));
            break;
        // (i.e. UNORDERED is a goto to target)
        case ConditionOperand.CMPL_NOT_EQUAL:
            if (VM.VerifyAssertions)
                VM._assert(c.branchIfUnordered());
            // Check whether val1 and val2 operands are the same
            if (!val1.similar(val2)) {
                s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, IA32ConditionOperand.PE(), // PF == 1
                target, new BranchProfileOperand(0f), IA32ConditionOperand.NE(), // ZF == 0
                (BranchOperand) (target.copy()), branchProfile));
                s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
            } else {
                // As val1 == val2 result of compare must be == or UNORDERED
                s.insertBefore(// PF == 1
                MIR_CondBranch.create(// PF == 1
                IA32_JCC, // PF == 1
                IA32ConditionOperand.PE(), target, branchProfile));
                s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
            }
            break;
        case ConditionOperand.CMPL_LESS:
            if (VM.VerifyAssertions)
                VM._assert(c.branchIfUnordered());
            s.insertBefore(// CF == 1
            MIR_CondBranch.create(// CF == 1
            IA32_JCC, // CF == 1
            IA32ConditionOperand.LLT(), target, branchProfile));
            s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
            break;
        case ConditionOperand.CMPG_GREATER_EQUAL:
            if (VM.VerifyAssertions)
                VM._assert(c.branchIfUnordered());
            s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, IA32ConditionOperand.PE(), // PF == 1
            target, new BranchProfileOperand(0f), IA32ConditionOperand.LLT(), // CF == 1
            testFailed, branchProfile));
            s.insertBefore(MIR_Branch.create(IA32_JMP, (BranchOperand) (target.copy())));
            break;
        case ConditionOperand.CMPG_GREATER:
            if (VM.VerifyAssertions)
                VM._assert(c.branchIfUnordered());
            s.insertBefore(MIR_CondBranch2.create(IA32_JCC2, IA32ConditionOperand.PE(), // PF == 1
            target, new BranchProfileOperand(0f), IA32ConditionOperand.LGT(), // ZF == 0 and CF == 0
            (BranchOperand) (target.copy()), branchProfile));
            s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
            break;
        case ConditionOperand.CMPL_LESS_EQUAL:
            if (VM.VerifyAssertions)
                VM._assert(c.branchIfUnordered());
            s.insertBefore(// CF == 1 or ZF == 1
            MIR_CondBranch.create(// CF == 1 or ZF == 1
            IA32_JCC, // CF == 1 or ZF == 1
            IA32ConditionOperand.LLE(), target, branchProfile));
            s.insertBefore(MIR_Branch.create(IA32_JMP, testFailed));
            break;
        default:
            OptimizingCompilerException.UNREACHABLE();
    }
    s.remove();
    return nextInstr;
}
Also used : LongConstantOperand(org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) IA32ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ia32.IA32ConditionOperand) StackLocationOperand(org.jikesrvm.compilers.opt.ir.operand.StackLocationOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) MemoryOperand(org.jikesrvm.compilers.opt.ir.operand.MemoryOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) IA32ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ia32.IA32ConditionOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand)

Aggregations

BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)33 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)29 BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)24 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)18 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)17 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)15 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)12 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)11 Register (org.jikesrvm.compilers.opt.ir.Register)10 BranchOperand (org.jikesrvm.compilers.opt.ir.operand.BranchOperand)9 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)9 TrapCodeOperand (org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand)8 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)8 NullConstantOperand (org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand)7 PowerPCConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ppc.PowerPCConditionOperand)5 RVMClass (org.jikesrvm.classloader.RVMClass)4 RVMMethod (org.jikesrvm.classloader.RVMMethod)4 RVMType (org.jikesrvm.classloader.RVMType)4 TypeReference (org.jikesrvm.classloader.TypeReference)4 AddressConstantOperand (org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand)4