Esempio n. 1
0
void CodeGen::genKeepAddressableFloat(GenTreePtr tree, regMaskTP *  regMaskIntPtr, regMaskTP *  regMaskFltPtr)
{
    regMaskTP regMaskInt, regMaskFlt;

    regMaskInt = *regMaskIntPtr;
    regMaskFlt = *regMaskFltPtr;

    *regMaskIntPtr = *regMaskFltPtr = 0;
        
    switch (tree->OperGet())
    {
    case GT_REG_VAR:
        // If register has been spilled, unspill it
        if (tree->gtFlags & GTF_SPILLED)
        {
            UnspillFloat(&compiler->lvaTable[tree->gtLclVarCommon.gtLclNum]);
        }        
        break;

    case GT_CNS_DBL:
        if (tree->gtFlags & GTF_SPILLED)
        {
            UnspillFloat(tree);
        }
        *regMaskFltPtr = genRegMaskFloat(tree->gtRegNum, tree->TypeGet());
        break;

    case GT_LCL_FLD:
    case GT_LCL_VAR:
    case GT_CLS_VAR:
        break;

    case GT_IND:
        if (regMaskFlt == RBM_NONE)
        {
            *regMaskIntPtr = genKeepAddressable(tree, regMaskInt, 0);
            *regMaskFltPtr = 0;
            return;
        } 
        __fallthrough;

    default:
        *regMaskIntPtr = 0;
        if (tree->gtFlags & GTF_SPILLED)
        {
            UnspillFloat(tree);
        }
        *regMaskFltPtr = genRegMaskFloat(tree->gtRegNum, tree->TypeGet());
        break;
    }
}
Esempio n. 2
0
void RegSet::SetLockedRegFloat(GenTree * tree, bool bValue)
{
    regNumber  reg     = tree->gtRegNum;
    var_types  type    = tree->TypeGet();    assert(varTypeIsFloating(type));
    regMaskTP  regMask = genRegMaskFloat(reg, tree->TypeGet());

    if (bValue)
    {
        JITDUMP("locking register %s\n", getRegNameFloat(reg, type));

        assert((rsGetMaskUsed() & regMask) == regMask);
        assert((rsGetMaskLock() & regMask) == 0);

        rsSetMaskLock( (rsGetMaskLock() | regMask) );
    }
    else
    {
        JITDUMP("unlocking register %s\n", getRegNameFloat(reg, type));

        assert((rsGetMaskUsed()   & regMask) == regMask);
        assert((rsGetMaskLock() & regMask) == regMask);

        rsSetMaskLock( (rsGetMaskLock() & ~regMask) );
    }
}
Esempio n. 3
0
void CodeGen::genDoneAddressableFloat(GenTreePtr      tree,
                                      regMaskTP       addrRegInt,
                                      regMaskTP       addrRegFlt,
                                      RegSet::KeepReg keptReg)
{
    assert(!(addrRegInt && addrRegFlt));

    if (addrRegInt)
    {
        return genDoneAddressable(tree, addrRegInt, keptReg);
    }
    else if (addrRegFlt)
    {
        if (keptReg == RegSet::KEEP_REG)
        {
            for (regNumber r = REG_FP_FIRST; r != REG_NA; r = regNextOfType(r, tree->TypeGet()))
            {
                regMaskTP mask = genRegMaskFloat(r, tree->TypeGet());
                // some masks take up more than one bit
                if ((mask & addrRegFlt) == mask)
                {
                    regSet.SetUsedRegFloat(tree, false);
                }
            }
        }
    }
}
Esempio n. 4
0
GenTreePtr CodeGen::genMakeAddressableFloat(GenTreePtr tree, 
                                            regMaskTP * regMaskIntPtr, 
                                            regMaskTP * regMaskFltPtr, 
                                            bool bCollapseConstantDoubles)
{    
    *regMaskIntPtr = *regMaskFltPtr = 0;

    switch (tree->OperGet())
    {    

    case GT_LCL_VAR:
        genMarkLclVar(tree);
        __fallthrough;

    case GT_REG_VAR:
    case GT_LCL_FLD:
    case GT_CLS_VAR:
        return tree;

    case GT_IND:
        // Try to make the address directly addressable

        if  (genMakeIndAddrMode(tree->gtOp.gtOp1,
                                tree,
                                false,
                                RBM_ALLFLOAT,
                                RegSet::KEEP_REG,
                                regMaskIntPtr,
                                false))
        {
            genUpdateLife(tree);
            return tree;
        }
        else
        {
            GenTreePtr addr = tree;
            tree = tree->gtOp.gtOp1;
            genCodeForTree(tree, 0);
            regSet.rsMarkRegUsed(tree, addr);

            *regMaskIntPtr = genRegMask(tree->gtRegNum);                        
            return addr;
        }

        // fall through

    default:
        genCodeForTreeFloat(tree);
        regSet.SetUsedRegFloat(tree, true);

        // update mask
        *regMaskFltPtr = genRegMaskFloat(tree->gtRegNum, tree->TypeGet());

        return tree;
        break;
    }    
}
Esempio n. 5
0
bool RegSet::IsLockedRegFloat(GenTreePtr tree)
{
    /* The value must be sitting in a register */
    assert(tree);
    assert(tree->gtFlags & GTF_REG_VAL);
    assert(varTypeIsFloating(tree->TypeGet()));

    regMaskTP  regMask = genRegMaskFloat(tree->gtRegNum, tree->TypeGet());
    return (rsGetMaskLock() & regMask) == regMask;
}
Esempio n. 6
0
void        CodeGen::genComputeAddressableFloat(GenTreePtr tree, 
                                                regMaskTP addrRegInt,
                                                regMaskTP addrRegFlt,
                                                RegSet::KeepReg keptReg,
                                                regMaskTP needReg,
                                                RegSet::KeepReg keepReg,
                                                bool freeOnly /* = false */)
{
    noway_assert(genStillAddressable(tree));
    noway_assert(varTypeIsFloating(tree->TypeGet()));

    genDoneAddressableFloat(tree, addrRegInt, addrRegFlt, keptReg);

    regNumber reg;
    if (tree->gtFlags & GTF_REG_VAL)
    {
        reg = tree->gtRegNum;
        if (freeOnly && !(genRegMaskFloat(reg, tree->TypeGet()) & regSet.RegFreeFloat()))
        {
            goto LOAD_REG;
        }
    }
    else
    {
        LOAD_REG:
            RegSet::RegisterPreference pref(needReg, RBM_NONE);
            reg = regSet.PickRegFloat(tree->TypeGet(), &pref);
            genLoadFloat(tree, reg);
    }

    genMarkTreeInReg(tree, reg);

    if (keepReg == RegSet::KEEP_REG)
    {
        regSet.SetUsedRegFloat(tree, true);
    }
}
Esempio n. 7
0
void RegSet::SetUsedRegFloat(GenTreePtr tree, bool bValue)
{
    /* The value must be sitting in a register */
    assert(tree);
    assert(tree->gtFlags & GTF_REG_VAL);

    var_types  type    = tree->TypeGet();
#ifdef _TARGET_ARM_
    if (type == TYP_STRUCT)
    {
        assert(m_rsCompiler->IsHfa(tree));
        type = TYP_FLOAT;
    }
#endif
    regNumber  regNum  = tree->gtRegNum;
    regMaskTP  regMask = genRegMaskFloat(regNum, type);

    if (bValue)
    {
        // Mark as used

#ifdef  DEBUG
        if  (m_rsCompiler->verbose)
        {
            printf("\t\t\t\t\t\t\tThe register %s currently holds ", 
                   getRegNameFloat(regNum, type));
            Compiler::printTreeID(tree);
            printf("\n");
        }
#endif

        assert((rsGetMaskLock() & regMask) == 0);

#if FEATURE_STACK_FP_X87
        assert((rsGetMaskUsed() & regMask) == 0);
#else
        /* Is the register used by two different values simultaneously? */

        if  (regMask & rsGetMaskUsed())
        {
            /* Save the preceding use information */

            rsRecMultiReg(regNum, type);
        }
#endif
        /* Set the register's bit in the 'used' bitset */

        rsSetMaskUsed( (rsGetMaskUsed() | regMask) );

        // Assign slot
        rsSetUsedTree(regNum, tree);
    }
    else
    {
        // Mark as free

#ifdef DEBUG
        if  (m_rsCompiler->verbose)
        {
            printf("\t\t\t\t\t\t\tThe register %s no longer holds ",
                   getRegNameFloat(regNum, type));
            Compiler::printTreeID(tree);
            printf("\n");
        }
#endif

        assert((rsGetMaskUsed() & regMask) == regMask);

        // Are we freeing a multi-use registers?

        if  (regMask & rsGetMaskMult())
        {
            // Free any multi-use registers
            rsMultRegFree(regMask);
            return;
        }

        rsSetMaskUsed( (rsGetMaskUsed() & ~regMask) );

        // Free slot
        rsFreeUsedTree(regNum, tree);
    }
}
Esempio n. 8
0
regNumber RegSet::PickRegFloat(var_types type, RegisterPreference *pref, bool bUsed)
{
    regMaskTP wantedMask;
    bool      tryBest = true;
    bool      tryOk   = true;
    bool      bSpill  = false;
    regNumber reg    = REG_NA;

    while (tryOk)
    {
        if (pref)
        {
            if (tryBest)
            {
                wantedMask = pref->best;
                tryBest = false;
            }
            else
            {
                assert(tryOk);
                wantedMask = pref->ok;
                tryOk = false;
            }
        }
        else// pref is NULL
        {
            wantedMask = RBM_ALLFLOAT;
            tryBest = false;
            tryOk = false;
        }
        
        // better not have asked for a non-fp register
        assert((wantedMask & ~RBM_ALLFLOAT) == 0);
   
        regMaskTP availMask = RegFreeFloat();
        regMaskTP OKmask = availMask & wantedMask;

        if (OKmask == 0)
        {
            if (tryOk)
            {
                // the pref->best mask doesn't work so try the pref->ok mask next
                continue;
            }

            if (bUsed)
            {
                // Allow used registers to be picked
                OKmask |= rsGetMaskUsed() & ~rsGetMaskLock();
                bSpill = true;
            }
        }
#if FEATURE_FP_REGALLOC
        regMaskTP restrictMask = (m_rsCompiler->raConfigRestrictMaskFP() | RBM_FLT_CALLEE_TRASH);
#endif

        for (unsigned i=0; i<ArrLen(pickOrder); i++)
        {
            regNumber r = pickOrder[i];
            if (!floatRegCanHoldType(r, type))
                continue;

            regMaskTP mask = genRegMaskFloat(r, type);

#if FEATURE_FP_REGALLOC
            if ((mask & restrictMask) != mask)
                continue;
#endif
            if ((OKmask & mask) == mask)
            {
                reg = r;
                goto RET;
            }
        }

        if (tryOk)
        {
            // We couldn't find a register using tryBest
            continue;
        }

        assert(!"Unable to find a free FP virtual register");
        NO_WAY("FP register allocator was too optimistic!");
    }
RET:
    if (bSpill)
    {
        m_rsCompiler->codeGen->SpillFloat(reg);
    }

#if FEATURE_FP_REGALLOC
    rsSetRegsModified(genRegMaskFloat(reg, type));
#endif

    return reg;
}
Esempio n. 9
0
void CodeGen::genFloatArith (GenTreePtr tree,
                             RegSet::RegisterPreference *tgtPref)
{
    var_types       type    = tree->TypeGet();
    genTreeOps      oper    = tree->OperGet();
    GenTreePtr      op1     = tree->gtGetOp1();
    GenTreePtr      op2     = tree->gtGetOp2();

    regNumber       tgtReg;
    unsigned        varNum;
    LclVarDsc   *   varDsc;
    VARSET_TP       varBit;

    assert(oper == GT_ADD ||
           oper == GT_SUB ||
           oper == GT_MUL ||
           oper == GT_DIV);

    RegSet::RegisterPreference defaultPref(RBM_ALLFLOAT, RBM_NONE);
    if (tgtPref == NULL)
    {
        tgtPref = &defaultPref;
    }

    // Is the op2 (RHS)more complex than op1 (LHS)?
    //
    if  (tree->gtFlags & GTF_REVERSE_OPS)
    {
        regMaskTP bestRegs = regSet.rsNarrowHint(RBM_ALLFLOAT, ~op1->gtRsvdRegs);
        RegSet::RegisterPreference pref(RBM_ALLFLOAT, bestRegs);

        // Evaluate op2 into a floating point register 
        //
        genCodeForTreeFloat(op2, &pref);
        regSet.SetUsedRegFloat(op2, true);

        // Evaluate op1 into any floating point register 
        //
        genCodeForTreeFloat(op1);
        regSet.SetUsedRegFloat(op1, true);

        regNumber  op1Reg  = op1->gtRegNum;
        regMaskTP  op1Mask = genRegMaskFloat(op1Reg, type);

        // Fix 388445 ARM JitStress WP7
        regSet.rsLockUsedReg(op1Mask);
        genRecoverReg(op2, RBM_ALLFLOAT, RegSet::KEEP_REG);
        noway_assert(op2->gtFlags & GTF_REG_VAL);
        regSet.rsUnlockUsedReg(op1Mask);

        regSet.SetUsedRegFloat(op1, false);
        regSet.SetUsedRegFloat(op2, false);
    }
    else
    {
        regMaskTP bestRegs = regSet.rsNarrowHint(RBM_ALLFLOAT, ~op2->gtRsvdRegs);
        RegSet::RegisterPreference pref(RBM_ALLFLOAT, bestRegs);

        // Evaluate op1 into a floating point register 
        //
        genCodeForTreeFloat(op1, &pref);
        regSet.SetUsedRegFloat(op1, true);

        // Evaluate op2 into any floating point register 
        //
        genCodeForTreeFloat(op2);
        regSet.SetUsedRegFloat(op2, true);
        
        regNumber  op2Reg  = op2->gtRegNum;
        regMaskTP  op2Mask = genRegMaskFloat(op2Reg, type);

        // Fix 388445 ARM JitStress WP7
        regSet.rsLockUsedReg(op2Mask);
        genRecoverReg(op1, RBM_ALLFLOAT, RegSet::KEEP_REG);
        noway_assert(op1->gtFlags & GTF_REG_VAL);
        regSet.rsUnlockUsedReg(op2Mask);

        regSet.SetUsedRegFloat(op2, false); 
        regSet.SetUsedRegFloat(op1, false);
    }

    tgtReg = regSet.PickRegFloat(type, tgtPref, true);

    noway_assert(op1->gtFlags & GTF_REG_VAL);
    noway_assert(op2->gtFlags & GTF_REG_VAL);

    inst_RV_RV_RV(ins_MathOp(oper, type), tgtReg, op1->gtRegNum, op2->gtRegNum, emitActualTypeSize(type));

    genCodeForTreeFloat_DONE(tree, tgtReg);
}
Esempio n. 10
0
void CodeGen::genFloatAssign(GenTree *tree)
{
    var_types   type       = tree->TypeGet();
    GenTreePtr  op1        = tree->gtGetOp1();
    GenTreePtr  op2        = tree->gtGetOp2();

    regMaskTP   needRegOp1 = RBM_ALLINT;
    regMaskTP   addrReg    = RBM_NONE;
    bool        volat      = false;        // Is this a volatile store
    bool        unaligned  = false;        // Is this an unaligned store
    regNumber   op2reg     = REG_NA;

#ifdef DEBUGGING_SUPPORT
    unsigned    lclVarNum  = compiler->lvaCount;
    unsigned    lclILoffs  = DUMMY_INIT(0);
#endif

    noway_assert(tree->OperGet() == GT_ASG);

    // Is the target a floating-point local variable?
    //  possibly even an enregistered floating-point local variable?
    //
    switch (op1->gtOper)
    {
        unsigned        varNum;
        LclVarDsc   *   varDsc;

    case GT_LCL_FLD:
        // Check for a misalignment on a Floating Point field
        //
        if (varTypeIsFloating(op1->TypeGet()))
        {                
            if ((op1->gtLclFld.gtLclOffs % emitTypeSize(op1->TypeGet())) != 0)
            {
                unaligned = true;
            }
        }
        break;

    case GT_LCL_VAR:
        varNum = op1->gtLclVarCommon.gtLclNum;
        noway_assert(varNum < compiler->lvaCount);
        varDsc = compiler->lvaTable + varNum;

 #ifdef DEBUGGING_SUPPORT
        // For non-debuggable code, every definition of a lcl-var has
        // to be checked to see if we need to open a new scope for it.
        // Remember the local var info to call siCheckVarScope
        // AFTER code generation of the assignment.
        //
        if (compiler->opts.compScopeInfo && !compiler->opts.compDbgCode && (compiler->info.compVarScopesCount > 0))
        {
            lclVarNum = varNum;
            lclILoffs = op1->gtLclVar.gtLclILoffs;
        }
 #endif

        // Dead Store assert (with min opts we may have dead stores)
        //
        noway_assert(!varDsc->lvTracked || compiler->opts.MinOpts() ||  !(op1->gtFlags & GTF_VAR_DEATH));

        // Does this variable live in a register?
        //
        if (genMarkLclVar(op1))
        {
             noway_assert(!compiler->opts.compDbgCode);   // We don't enregister any floats with debug codegen

            // Get hold of the target register
            //
            regNumber op1Reg = op1->gtRegVar.gtRegNum;

            // the variable being assigned should be dead in op2
            assert(!varDsc->lvTracked || !VarSetOps::IsMember(compiler, genUpdateLiveSetForward(op2), varDsc->lvVarIndex));

            // Setup register preferencing, so that we try to target the op1 enregistered variable
            //
            regMaskTP bestMask = genRegMask(op1Reg);
            if (type==TYP_DOUBLE)
            {
                assert((bestMask & RBM_DBL_REGS) != 0);
                bestMask |= genRegMask(REG_NEXT(op1Reg));
            }
            RegSet::RegisterPreference pref(RBM_ALLFLOAT, bestMask);

            // Evaluate op2 into a floating point register 
            //
            genCodeForTreeFloat(op2, &pref);
    
            noway_assert(op2->gtFlags & GTF_REG_VAL);

            // Make sure the value ends up in the right place ...
            // For example if op2 is a call that returns a result 
            // in REG_F0, we will need to do a move instruction here
            //
            if ((op2->gtRegNum != op1Reg) || (op2->TypeGet() != type))
            {
                regMaskTP spillRegs = regSet.rsMaskUsed & genRegMaskFloat(op1Reg, op1->TypeGet());
                if  (spillRegs != 0)
                    regSet.rsSpillRegs(spillRegs);

                assert(type == op1->TypeGet());

                inst_RV_RV(ins_FloatConv(type, op2->TypeGet()), op1Reg, op2->gtRegNum, type);
            }
            genUpdateLife(op1);
            goto DONE_ASG;
        }
        break;

    case GT_CLS_VAR:
    case GT_IND:
        // Check for a volatile/unaligned store
        //
        assert((op1->OperGet() == GT_CLS_VAR) || (op1->OperGet() == GT_IND));   // Required for GTF_IND_VOLATILE flag to be valid
        if (op1->gtFlags & GTF_IND_VOLATILE)
            volat = true;
        if (op1->gtFlags & GTF_IND_UNALIGNED)
            unaligned = true;
        break;

    default:
        break;
    }

    // Is the value being assigned an enregistered floating-point local variable?
    //
    switch (op2->gtOper)
    {
    case GT_LCL_VAR:

        if  (!genMarkLclVar(op2))
            break;

        __fallthrough;

    case GT_REG_VAR:

        // We must honor the order evalauation in case op1 reassigns our op2 register
        //
        if  (tree->gtFlags & GTF_REVERSE_OPS)
            break;

        // Is there an implicit conversion that we have to insert?
        // Handle this case with the normal cases below.
        //
        if (type != op2->TypeGet())
            break;

        // Make the target addressable
        //
        addrReg = genMakeAddressable(op1, needRegOp1, RegSet::KEEP_REG, true);

        noway_assert(op2->gtFlags & GTF_REG_VAL);
        noway_assert(op2->IsRegVar());
        
        op2reg = op2->gtRegVar.gtRegNum; 
        genUpdateLife(op2);

        goto CHK_VOLAT_UNALIGN;
    default:
        break;
    }

    // Is the op2 (RHS) more complex than op1 (LHS)?
    //
    if  (tree->gtFlags & GTF_REVERSE_OPS)
    {
        regMaskTP bestRegs = regSet.rsNarrowHint(RBM_ALLFLOAT, ~op1->gtRsvdRegs);
        RegSet::RegisterPreference pref(RBM_ALLFLOAT, bestRegs);

        // Generate op2 (RHS) into a floating point register
        //
        genCodeForTreeFloat(op2, &pref);
        regSet.SetUsedRegFloat(op2, true);

        // Make the target addressable
        //
        addrReg = genMakeAddressable(op1,
                                     needRegOp1,
                                     RegSet::KEEP_REG, true);

        genRecoverReg(op2, RBM_ALLFLOAT, RegSet::KEEP_REG);
        noway_assert(op2->gtFlags & GTF_REG_VAL);
        regSet.SetUsedRegFloat(op2, false);
    }
    else
    {
        needRegOp1 = regSet.rsNarrowHint(needRegOp1, ~op2->gtRsvdRegs);

        // Make the target addressable
        //
        addrReg = genMakeAddressable(op1,
                                     needRegOp1,
                                     RegSet::KEEP_REG, true);
        

        // Generate the RHS into any floating point register
        genCodeForTreeFloat(op2);

    }
    noway_assert(op2->gtFlags & GTF_REG_VAL);

    op2reg = op2->gtRegNum;

    // Is there an implicit conversion that we have to insert?
    //
    if (type != op2->TypeGet())
    {
        regMaskTP bestMask = genRegMask(op2reg);
        if (type==TYP_DOUBLE)
        {
            if (bestMask & RBM_DBL_REGS)
            {
                bestMask |= genRegMask(REG_NEXT(op2reg));
            }
            else
            {
                bestMask |= genRegMask(REG_PREV(op2reg));
            }
        }
        RegSet::RegisterPreference op2Pref(RBM_ALLFLOAT, bestMask);
        op2reg = regSet.PickRegFloat(type, &op2Pref);

        inst_RV_RV(ins_FloatConv(type, op2->TypeGet()), op2reg, op2->gtRegNum, type);
    }

    // Make sure the LHS is still addressable
    //
    addrReg = genKeepAddressable(op1, addrReg);

CHK_VOLAT_UNALIGN:
        
    regSet.rsLockUsedReg(addrReg);  // Must prevent unaligned regSet.rsGrabReg from choosing an addrReg
        
    if (volat)
    {
        // Emit a memory barrier instruction before the store
        instGen_MemoryBarrier();
    }
    if (unaligned)
    {
        var_types storeType = op1->TypeGet();
        assert(storeType == TYP_DOUBLE || storeType == TYP_FLOAT);

        // Unaligned Floating-Point Stores must be done using the integer register(s)
        regNumber  intRegLo    = regSet.rsGrabReg(RBM_ALLINT);
        regNumber  intRegHi    = REG_NA;
        regMaskTP  tmpLockMask = genRegMask(intRegLo);

        if (storeType == TYP_DOUBLE)
        {
            intRegHi     = regSet.rsGrabReg(RBM_ALLINT & ~genRegMask(intRegLo));
            tmpLockMask |= genRegMask(intRegHi);
        }

        // move the FP register over to the integer register(s)
        //
        if  (storeType == TYP_DOUBLE)
        {
            getEmitter()->emitIns_R_R_R(INS_vmov_d2i, EA_8BYTE, intRegLo, intRegHi, op2reg);
            regTracker.rsTrackRegTrash(intRegHi);
        }
        else 
        {
            getEmitter()->emitIns_R_R(INS_vmov_f2i, EA_4BYTE, intRegLo, op2reg);
        }
        regTracker.rsTrackRegTrash(intRegLo);

        regSet.rsLockReg(tmpLockMask);     // Temporarily lock the intRegs 
        op1->gtType = TYP_INT;      // Temporarily change the type to TYP_INT
        
        inst_TT_RV(ins_Store(TYP_INT), op1, intRegLo);

        if (storeType == TYP_DOUBLE)
        {
            inst_TT_RV(ins_Store(TYP_INT), op1, intRegHi, 4);
        }
        
        op1->gtType = storeType;    // Change the type back to the floating point type
        regSet.rsUnlockReg(tmpLockMask);   // Unlock the intRegs
    }
    else
    {
        // Move the value into the target
        //        
        inst_TT_RV(ins_Store(op1->TypeGet()), op1, op2reg);
    }

    // Free up anything that was tied up by the LHS
    //
    regSet.rsUnlockUsedReg(addrReg);
    genDoneAddressable(op1, addrReg, RegSet::KEEP_REG);

DONE_ASG:

    genUpdateLife(tree);

#ifdef DEBUGGING_SUPPORT
    /* For non-debuggable code, every definition of a lcl-var has
     * to be checked to see if we need to open a new scope for it.
     */
    if (lclVarNum < compiler->lvaCount)
        siCheckVarScope(lclVarNum, lclILoffs);
#endif
}