Repository: dotnet/runtime
File: src/coreclr/jit/compiler.h (C/C++)

Code before:
    GenTree* optAssertionProp_BlockStore(ASSERT_VALARG_TP assertions, GenTreeBlk* store, Statement* stmt);
    GenTree* optAssertionProp_ModDiv(ASSERT_VALARG_TP assertions, GenTreeOp* tree, Statement* stmt, BasicBlock* block);
    GenTree* optAssertionProp_Return(ASSERT_VALARG_TP assertions, GenTreeOp* ret, Statement* stmt);
    GenTree* optAssertionProp_Ind(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt);
    GenTree* optAssertionProp_Cast(ASSERT_VALARG_TP assertions, GenTreeCast* cast, Statement* stmt, BasicBlock* block);
    GenTree* optAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCall* call, Statement* stmt);
    GenTree* optAssertionProp_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt, BasicBlock* block);
    GenTree* optAssertionProp_Comma(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt);
    GenTree* optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt);
    GenTree* optAssertionPropGlobal_RelOp(ASSERT_VALARG_TP assertions,
                                          GenTree*         tree,
                                          Statement*       stmt,
                                          BasicBlock*      block);
    GenTree* optAssertionPropLocal_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt);
    GenTree* optAssertionProp_Update(GenTree* newTree, GenTree* tree, Statement* stmt);
    GenTree* optNonNullAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCall* call);
    bool     optNonNullAssertionProp_Ind(ASSERT_VALARG_TP assertions, GenTree* indir);
    bool     optWriteBarrierAssertionProp_StoreInd(ASSERT_VALARG_TP assertions, GenTreeStoreInd* indir);

    enum class AssertVisit
    {
        Continue,
        Abort,
    };

    //--------------------------------------------------------------------------------
    // optVisitReachingAssertions: given a vn, call the specified callback function on all
    //    the assertions that reach it via PHI definitions if any.
    //
    // Arguments:
    //    vn         - The vn to visit all the reaching assertions for
    //    argVisitor - The callback function to call on the vn and its reaching assertions
    //
    // Return Value:
    //    AssertVisit::Aborted  - an argVisitor returned AssertVisit::Abort, we stop the walk and return
    //    AssertVisit::Continue - all argVisitor returned AssertVisit::Continue
    //
    template <typename TAssertVisitor>
    AssertVisit optVisitReachingAssertions(ValueNum vn, TAssertVisitor argVisitor)
    {
        VNPhiDef phiDef;
        if (!vnStore->GetPhiDef(vn, &phiDef))
        {
            // We assume that the caller already checked assertions for the current block, so we're
            // interested only in assertions for PHI definitions.
            return AssertVisit::Abort;
        }

        LclSsaVarDsc*        ssaDef = lvaGetDesc(phiDef.LclNum)->GetPerSsaData(phiDef.SsaDef);
        GenTreeLclVarCommon* node   = ssaDef->GetDefNode();
        assert(node->IsPhiDefn());

Review comment (suggestion):
Moved from `assertionprop.cpp` without changes, the impl has to live in .h to be used from multiple places due to C++ templates used.

Code after:
    GenTree* optAssertionProp_BlockStore(ASSERT_VALARG_TP assertions, GenTreeBlk* store, Statement* stmt);
    GenTree* optAssertionProp_ModDiv(ASSERT_VALARG_TP assertions, GenTreeOp* tree, Statement* stmt, BasicBlock* block);
    GenTree* optAssertionProp_Return(ASSERT_VALARG_TP assertions, GenTreeOp* ret, Statement* stmt);
    GenTree* optAssertionProp_Ind(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt);
    GenTree* optAssertionProp_Cast(ASSERT_VALARG_TP assertions, GenTreeCast* cast, Statement* stmt, BasicBlock* block);
    GenTree* optAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCall* call, Statement* stmt);
    GenTree* optAssertionProp_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt, BasicBlock* block);
    GenTree* optAssertionProp_Comma(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt);
    GenTree* optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt);
    GenTree* optAssertionPropGlobal_RelOp(ASSERT_VALARG_TP assertions,
                                          GenTree*         tree,
                                          Statement*       stmt,
                                          BasicBlock*      block);
    GenTree* optAssertionPropLocal_RelOp(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt);
    GenTree* optAssertionProp_Update(GenTree* newTree, GenTree* tree, Statement* stmt);
    GenTree* optNonNullAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCall* call);
    bool     optNonNullAssertionProp_Ind(ASSERT_VALARG_TP assertions, GenTree* indir);
    bool     optWriteBarrierAssertionProp_StoreInd(ASSERT_VALARG_TP assertions, GenTreeStoreInd* indir);

    enum class AssertVisit
    {
        Continue,
        Abort,
    };

    template <typename TAssertVisitor>
    AssertVisit optVisitReachingAssertions(ValueNum vn, TAssertVisitor argVisitor);

    void optAssertionProp_RangeProperties(ASSERT_VALARG_TP assertions,
                                          GenTree*         tree,
                                          Statement*       stmt,
                                          BasicBlock*      block,
                                          bool*            isKnownNonZero,
                                          bool*            isKnownNonNegative);

    // Implied assertion functions.
    void optImpliedAssertions(AssertionIndex assertionIndex, ASSERT_TP& activeAssertions);
    void optImpliedByTypeOfAssertions(ASSERT_TP& activeAssertions);
    bool optCreateJumpTableImpliedAssertions(BasicBlock* switchBb);
    void optImpliedByConstAssertion(AssertionDsc* curAssertion, ASSERT_TP& result);

#ifdef DEBUG
    void optPrintAssertion(AssertionDsc* newAssertion, AssertionIndex assertionIndex = 0);
    void optPrintAssertionIndex(AssertionIndex index);
    void optPrintAssertionIndices(ASSERT_TP assertions);
    void optDebugCheckAssertion(AssertionDsc* assertion);
    void optDebugCheckAssertions(AssertionIndex AssertionIndex);
#endif

    ASSERT_VALRET_TP optGetEdgeAssertions(const BasicBlock* block, const BasicBlock* blockPred) const;