Repository: dotnet/runtime
File: src/coreclr/jit/liveness.cpp (C++)

Code before:
{
    assert((tree->OperIsLocal() && !tree->OperIs(GT_PHI_ARG)) || tree->OperIs(GT_LCL_ADDR));

    const unsigned   lclNum = tree->GetLclNum();
    LclVarDsc* const varDsc = m_compiler->lvaGetDesc(lclNum);

    // We should never encounter a reference to a lclVar that has a zero refCnt.
    if (varDsc->lvRefCnt(m_compiler->lvaRefCountState) == 0 && (!varTypeIsPromotable(varDsc) || !varDsc->lvPromoted))
    {
        JITDUMP("Found reference to V%02u with zero refCnt.\n", lclNum);
        assert(!"We should never encounter a reference to a lclVar that has a zero refCnt.");
        varDsc->setLvRefCnt(1);
    }

    const bool isDef     = ((tree->gtFlags & GTF_VAR_DEF) != 0);
    const bool isFullDef = isDef && ((tree->gtFlags & GTF_VAR_USEASG) == 0);
    const bool isUse     = TLiveness::SsaLiveness ? !isFullDef : !isDef;

    if (varDsc->lvTracked)
    {
        assert(varDsc->lvVarIndex < m_compiler->lvaTrackedCount);

        // We don't treat stores to tracked locals as modifications of ByrefExposed memory;
        // Make sure no tracked local is addr-exposed, to make sure we don't incorrectly CSE byref
        // loads aliasing it across a store to it.
        assert(!varDsc->IsAddressExposed());

        if (TLiveness::IsLIR && (varDsc->lvType != TYP_STRUCT) && !varTypeIsMultiReg(varDsc))
        {
            // If this is an enregisterable variable that is not marked doNotEnregister and not defined via address,
            // we should only see direct references (not ADDRs).
            assert(varDsc->lvDoNotEnregister || varDsc->lvDefinedViaAddress ||
                   tree->OperIs(GT_LCL_VAR, GT_STORE_LCL_VAR));
        }

        if (isUse && !VarSetOps::IsMember(m_compiler, m_curDefSet, varDsc->lvVarIndex))
        {
            // This is an exposed use; add it to the set of uses.
            VarSetOps::AddElemD(m_compiler, m_curUseSet, varDsc->lvVarIndex);
        }

        if (TLiveness::SsaLiveness ? isDef : isFullDef)
        {
            // This is a def, add it to the set of defs.
            VarSetOps::AddElemD(m_compiler, m_curDefSet, varDsc->lvVarIndex);
        }
    }
    else
    {
        if (TLiveness::ComputeMemoryLiveness && varDsc->IsAddressExposed())
        {

Review comment (bug):
This comment says tracked locals are never addr-exposed to avoid incorrect ByrefExposed/CSE behavior, but the new assert now explicitly allows addr-exposed tracked locals when `TrackAddressExposedLocals` is true and memory liveness is off. Please update the comment to document this exception and why it is safe (no memory liveness/CSE modelling in that mode).
```suggestion
        // We don't treat stores to tracked locals as modifications of ByrefExposed memory.
        // In modes where we model memory liveness/ByrefExposed for CSE, no tracked local may be
        // addr-exposed, so that we don't incorrectly CSE byref loads aliasing it across a store.
        // The only exception is when TrackAddressExposedLocals is true and ComputeMemoryLiveness
        // is false: in that mode we track liveness of addr-exposed locals explicitly and do not
        // rely on ByrefExposed/memory liveness or CSE modelling for them, so it is safe to allow
        // addr-exposed tracked locals.
```

Code after:
void Liveness<TLiveness>::MarkUseDef(GenTreeLclVarCommon* tree)
{
    assert((tree->OperIsLocal() && !tree->OperIs(GT_PHI_ARG)) || tree->OperIs(GT_LCL_ADDR));

    const unsigned   lclNum = tree->GetLclNum();
    LclVarDsc* const varDsc = m_compiler->lvaGetDesc(lclNum);

    // We should never encounter a reference to a lclVar that has a zero refCnt.
    if (varDsc->lvRefCnt(m_compiler->lvaRefCountState) == 0 && (!varTypeIsPromotable(varDsc) || !varDsc->lvPromoted))
    {
        JITDUMP("Found reference to V%02u with zero refCnt.\n", lclNum);
        assert(!"We should never encounter a reference to a lclVar that has a zero refCnt.");
        varDsc->setLvRefCnt(1);
    }

    const bool isDef     = ((tree->gtFlags & GTF_VAR_DEF) != 0);
    const bool isFullDef = isDef && ((tree->gtFlags & GTF_VAR_USEASG) == 0);
    const bool isUse     = TLiveness::SsaLiveness ? !isFullDef : !isDef;

    if (varDsc->lvTracked)
    {
        assert(varDsc->lvVarIndex < m_compiler->lvaTrackedCount);

        // We don't treat stores to tracked locals as modifications of ByrefExposed memory;
        // Make sure no tracked local is addr-exposed, to make sure we don't incorrectly CSE byref
        // loads aliasing it across a store to it.
        assert(!varDsc->IsAddressExposed() ||
               (TLiveness::TrackAddressExposedLocals && !TLiveness::ComputeMemoryLiveness));

        if (TLiveness::IsLIR && (varDsc->lvType != TYP_STRUCT) && !varTypeIsMultiReg(varDsc))
        {
            // If this is an enregisterable variable that is not marked doNotEnregister and not defined via address,
            // we should only see direct references (not ADDRs).
            assert(varDsc->lvDoNotEnregister || varDsc->lvDefinedViaAddress ||
                   tree->OperIs(GT_LCL_VAR, GT_STORE_LCL_VAR));
        }

        if (isUse && !VarSetOps::IsMember(m_compiler, m_curDefSet, varDsc->lvVarIndex))
        {
            // This is an exposed use; add it to the set of uses.
            VarSetOps::AddElemD(m_compiler, m_curUseSet, varDsc->lvVarIndex);
        }

        if (TLiveness::SsaLiveness ? isDef : isFullDef)
        {
            // This is a def, add it to the set of defs.
            VarSetOps::AddElemD(m_compiler, m_curDefSet, varDsc->lvVarIndex);
        }
    }
    else
    {