Example #1
0
//------------------------------------------------------------------------
// DecomposeLclVar: Decompose GT_LCL_VAR.
//
// Arguments:
//    use - the LIR::Use object for the def that needs to be decomposed.
//
// Return Value:
//    The next node to process.
//
GenTree* DecomposeLongs::DecomposeLclVar(LIR::Use& use)
{
    assert(use.IsInitialized());
    assert(use.Def()->OperGet() == GT_LCL_VAR);

    GenTree*   tree   = use.Def();
    unsigned   varNum = tree->AsLclVarCommon()->gtLclNum;
    LclVarDsc* varDsc = m_compiler->lvaTable + varNum;
    m_compiler->lvaDecRefCnts(tree);

    GenTree* loResult = tree;
    loResult->gtType  = TYP_INT;

    GenTree* hiResult = m_compiler->gtNewLclLNode(varNum, TYP_INT);
    hiResult->CopyCosts(loResult);
    BlockRange().InsertAfter(loResult, hiResult);

    if (varDsc->lvPromoted)
    {
        assert(varDsc->lvFieldCnt == 2);
        unsigned loVarNum = varDsc->lvFieldLclStart;
        unsigned hiVarNum = loVarNum + 1;
        loResult->AsLclVarCommon()->SetLclNum(loVarNum);
        hiResult->AsLclVarCommon()->SetLclNum(hiVarNum);
    }
    else
    {
        noway_assert(varDsc->lvLRACandidate == false);

        loResult->SetOper(GT_LCL_FLD);
        loResult->AsLclFld()->gtLclOffs  = 0;
        loResult->AsLclFld()->gtFieldSeq = FieldSeqStore::NotAField();

        hiResult->SetOper(GT_LCL_FLD);
        hiResult->AsLclFld()->gtLclOffs  = 4;
        hiResult->AsLclFld()->gtFieldSeq = FieldSeqStore::NotAField();
    }

    m_compiler->lvaIncRefCnts(loResult);
    m_compiler->lvaIncRefCnts(hiResult);

    return FinalizeDecomposition(use, loResult, hiResult);
}
Example #2
0
//------------------------------------------------------------------------
// DecomposeLclVar: Decompose GT_LCL_VAR.
//
// Arguments:
//    ppTree - the tree to decompose
//    data - tree walk context
//
// Return Value:
//    None.
//
void DecomposeLongs::DecomposeLclVar(GenTree** ppTree, Compiler::fgWalkData* data)
{
    assert(ppTree != nullptr);
    assert(*ppTree != nullptr);
    assert(data != nullptr);
    assert((*ppTree)->OperGet() == GT_LCL_VAR);

    GenTree* tree = *ppTree;
    unsigned varNum = tree->AsLclVarCommon()->gtLclNum;
    LclVarDsc* varDsc = m_compiler->lvaTable + varNum;
    m_compiler->lvaDecRefCnts(tree);

    GenTree* loResult = tree;
    loResult->gtType = TYP_INT;
    GenTree* hiResult = m_compiler->gtNewLclLNode(varNum, TYP_INT);

    if (varDsc->lvPromoted)
    {
        assert(varDsc->lvFieldCnt == 2);
        unsigned loVarNum = varDsc->lvFieldLclStart;
        unsigned hiVarNum = loVarNum + 1;
        loResult->AsLclVarCommon()->SetLclNum(loVarNum);
        hiResult->AsLclVarCommon()->SetLclNum(hiVarNum);
    }
    else
    {
        noway_assert(varDsc->lvLRACandidate == false);

        loResult->SetOper(GT_LCL_FLD);
        loResult->AsLclFld()->gtLclOffs = 0;
        loResult->AsLclFld()->gtFieldSeq = FieldSeqStore::NotAField();

        hiResult->SetOper(GT_LCL_FLD);
        hiResult->AsLclFld()->gtLclOffs = 4;
        hiResult->AsLclFld()->gtFieldSeq = FieldSeqStore::NotAField();
    }

    m_compiler->lvaIncRefCnts(loResult);
    m_compiler->lvaIncRefCnts(hiResult);

    FinalizeDecomposition(ppTree, data, loResult, hiResult);
}
Example #3
0
//------------------------------------------------------------------------
// DecomposeLclFld: Decompose GT_LCL_FLD.
//
// Arguments:
//    use - the LIR::Use object for the def that needs to be decomposed.
//
// Return Value:
//    The next node to process.
//
GenTree* DecomposeLongs::DecomposeLclFld(LIR::Use& use)
{
    assert(use.IsInitialized());
    assert(use.Def()->OperGet() == GT_LCL_FLD);

    GenTree*       tree     = use.Def();
    GenTreeLclFld* loResult = tree->AsLclFld();
    loResult->gtType        = TYP_INT;

    GenTree* hiResult = m_compiler->gtNewLclFldNode(loResult->gtLclNum, TYP_INT, loResult->gtLclOffs + 4);
    Range().InsertAfter(loResult, hiResult);

    return FinalizeDecomposition(use, loResult, hiResult);
}
Example #4
0
//------------------------------------------------------------------------
// DecomposeLclFld: Decompose GT_LCL_FLD.
//
// Arguments:
//    ppTree - the tree to decompose
//    data - tree walk context
//
// Return Value:
//    None.
//
void DecomposeLongs::DecomposeLclFld(GenTree** ppTree, Compiler::fgWalkData* data)
{
    assert(ppTree != nullptr);
    assert(*ppTree != nullptr);
    assert(data != nullptr);
    assert((*ppTree)->OperGet() == GT_LCL_FLD);

    GenTree* tree = *ppTree;
    GenTreeLclFld* loResult = tree->AsLclFld();
    loResult->gtType = TYP_INT;

    GenTree* hiResult = m_compiler->gtNewLclFldNode(loResult->gtLclNum,
                                              TYP_INT,
                                              loResult->gtLclOffs + 4);

    FinalizeDecomposition(ppTree, data, loResult, hiResult);
}
Example #5
0
//------------------------------------------------------------------------
// DecomposeStoreLclVar: Decompose GT_STORE_LCL_VAR.
//
// Arguments:
//    ppTree - the tree to decompose
//    data - tree walk context
//
// Return Value:
//    None.
//
void DecomposeLongs::DecomposeStoreLclVar(GenTree** ppTree, Compiler::fgWalkData* data)
{
    assert(ppTree != nullptr);
    assert(*ppTree != nullptr);
    assert(data != nullptr);
    assert((*ppTree)->OperGet() == GT_STORE_LCL_VAR);
    assert(m_compiler->compCurStmt != nullptr);

    GenTreeStmt* curStmt = m_compiler->compCurStmt->AsStmt();

    GenTree* tree = *ppTree;
    GenTree* nextTree = tree->gtNext;
    GenTree* rhs = tree->gtGetOp1();
    if ((rhs->OperGet() == GT_PHI) || (rhs->OperGet() == GT_CALL))
    {
        // GT_CALLs are not decomposed, so will not be converted to GT_LONG
        // GT_STORE_LCL_VAR = GT_CALL are handled in genMultiRegCallStoreToLocal
        return;
    }

    noway_assert(rhs->OperGet() == GT_LONG);
    unsigned varNum = tree->AsLclVarCommon()->gtLclNum;
    LclVarDsc* varDsc = m_compiler->lvaTable + varNum;
    m_compiler->lvaDecRefCnts(tree);

    GenTree* loRhs = rhs->gtGetOp1();
    GenTree* hiRhs = rhs->gtGetOp2();
    GenTree* hiStore = m_compiler->gtNewLclLNode(varNum, TYP_INT);

    if (varDsc->lvPromoted)
    {
        assert(varDsc->lvFieldCnt == 2);

        unsigned loVarNum = varDsc->lvFieldLclStart;
        unsigned hiVarNum = loVarNum + 1;
        tree->AsLclVarCommon()->SetLclNum(loVarNum);
        hiStore->SetOper(GT_STORE_LCL_VAR);
        hiStore->AsLclVarCommon()->SetLclNum(hiVarNum);
    }
    else
    {
        noway_assert(varDsc->lvLRACandidate == false);

        tree->SetOper(GT_STORE_LCL_FLD);
        tree->AsLclFld()->gtLclOffs = 0;
        tree->AsLclFld()->gtFieldSeq = FieldSeqStore::NotAField();

        hiStore->SetOper(GT_STORE_LCL_FLD);
        hiStore->AsLclFld()->gtLclOffs = 4;
        hiStore->AsLclFld()->gtFieldSeq = FieldSeqStore::NotAField();
    }

    tree->gtOp.gtOp1 = loRhs;
    tree->gtType = TYP_INT;

    loRhs->gtNext = tree;
    tree->gtPrev = loRhs;

    hiStore->gtOp.gtOp1 = hiRhs;
    hiStore->CopyCosts(tree);
    hiStore->gtFlags |= GTF_VAR_DEF;

    m_compiler->lvaIncRefCnts(tree);
    m_compiler->lvaIncRefCnts(hiStore);

    tree->gtNext = hiRhs;
    hiRhs->gtPrev = tree;
    hiRhs->gtNext = hiStore;
    hiStore->gtPrev = hiRhs;
    hiStore->gtNext = nextTree;
    if (nextTree != nullptr)
    {
        nextTree->gtPrev = hiStore;
    }
    nextTree = hiRhs;

    bool isEmbeddedStmt = !curStmt->gtStmtIsTopLevel();
    if (!isEmbeddedStmt)
    {
        tree->gtNext = nullptr;
        hiRhs->gtPrev = nullptr;
    }

    InsertNodeAsStmt(hiStore);
}
Example #6
0
//------------------------------------------------------------------------
// DecomposeStoreLclVar: Decompose GT_STORE_LCL_VAR.
//
// Arguments:
//    use - the LIR::Use object for the def that needs to be decomposed.
//
// Return Value:
//    The next node to process.
//
GenTree* DecomposeLongs::DecomposeStoreLclVar(LIR::Use& use)
{
    assert(use.IsInitialized());
    assert(use.Def()->OperGet() == GT_STORE_LCL_VAR);

    GenTree* tree = use.Def();
    GenTree* rhs  = tree->gtGetOp1();
    if ((rhs->OperGet() == GT_PHI) || (rhs->OperGet() == GT_CALL) ||
            ((rhs->OperGet() == GT_MUL_LONG) && (rhs->gtFlags & GTF_MUL_64RSLT) != 0))
    {
        // GT_CALLs are not decomposed, so will not be converted to GT_LONG
        // GT_STORE_LCL_VAR = GT_CALL are handled in genMultiRegCallStoreToLocal
        // GT_MULs are not decomposed, so will not be converted to GT_LONG
        return tree->gtNext;
    }

    noway_assert(rhs->OperGet() == GT_LONG);
    unsigned   varNum = tree->AsLclVarCommon()->gtLclNum;
    LclVarDsc* varDsc = m_compiler->lvaTable + varNum;
    m_compiler->lvaDecRefCnts(tree);

    GenTree* loRhs   = rhs->gtGetOp1();
    GenTree* hiRhs   = rhs->gtGetOp2();
    GenTree* hiStore = m_compiler->gtNewLclLNode(varNum, TYP_INT);

    if (varDsc->lvPromoted)
    {
        assert(varDsc->lvFieldCnt == 2);

        unsigned loVarNum = varDsc->lvFieldLclStart;
        unsigned hiVarNum = loVarNum + 1;
        tree->AsLclVarCommon()->SetLclNum(loVarNum);
        hiStore->SetOper(GT_STORE_LCL_VAR);
        hiStore->AsLclVarCommon()->SetLclNum(hiVarNum);
    }
    else
    {
        noway_assert(varDsc->lvLRACandidate == false);

        tree->SetOper(GT_STORE_LCL_FLD);
        tree->AsLclFld()->gtLclOffs  = 0;
        tree->AsLclFld()->gtFieldSeq = FieldSeqStore::NotAField();

        hiStore->SetOper(GT_STORE_LCL_FLD);
        hiStore->AsLclFld()->gtLclOffs  = 4;
        hiStore->AsLclFld()->gtFieldSeq = FieldSeqStore::NotAField();
    }

    // 'tree' is going to steal the loRhs node for itself, so we need to remove the
    // GT_LONG node from the threading.
    Range().Remove(rhs);

    tree->gtOp.gtOp1 = loRhs;
    tree->gtType     = TYP_INT;

    hiStore->gtOp.gtOp1 = hiRhs;
    hiStore->gtFlags |= GTF_VAR_DEF;

    m_compiler->lvaIncRefCnts(tree);
    m_compiler->lvaIncRefCnts(hiStore);

    Range().InsertAfter(tree, hiStore);

    return hiStore->gtNext;
}