diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp
index 5d105881933fa5..fd4eec7118ce49 100644
--- a/src/coreclr/jit/assertionprop.cpp
+++ b/src/coreclr/jit/assertionprop.cpp
@@ -3685,16 +3685,21 @@ GenTree* Compiler::optAssertionProp_Comma(ASSERT_VALARG_TP assertions, GenTree*
     return nullptr;
 }
 
-/*****************************************************************************
- *
- *  Given a tree consisting of a Ind and a set of available assertions, we try
- *  to propagate an assertion and modify the Ind tree if we can. We pass in the
- *  root of the tree via 'stmt', for local copy prop 'stmt' will be nullptr.
- *
- *  Returns the modified tree, or nullptr if no assertion prop took place.
- *
- */
-
+//------------------------------------------------------------------------
+// optAssertionProp_Ind: see if we can prove the indirection can't cause
+//    and exception.
+//
+// Arguments:
+//   assertions  - set of live assertions
+//   tree        - tree to possibly optimize
+//   stmt        - statement containing the tree
+//
+// Returns:
+//   The modified tree, or nullptr if no assertion prop took place.
+//
+// Notes:
+//   stmt may be nullptr during local assertion prop
+//
 GenTree* Compiler::optAssertionProp_Ind(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt)
 {
     assert(tree->OperIsIndir());
@@ -3742,16 +3747,26 @@ GenTree* Compiler::optAssertionProp_Ind(ASSERT_VALARG_TP assertions, GenTree* tr
     return nullptr;
 }
 
-/*****************************************************************************
- *  Check if a non-null assertion can be made about the input operand "op"
- *  from the set of "assertions," or implicitly from the value number on "op."
- *
- *  Sets "pVnBased" if the assertion is value number based. If no matching
- *  assertions are found from the table, then returns "NO_ASSERTION_INDEX."
- *
- *  Note: If both VN and assertion table yield a matching assertion, "pVnBased"
- *  is only set and the return value is "NO_ASSERTION_INDEX."
- */
+//------------------------------------------------------------------------
+// optAssertionIsNonNull: see if we can prove a tree's value will be non-null
+//   based on assertions
+//
+// Arguments:
+//   op - tree to check
+//   assertions  - set of live assertions
+//   pVnBased - [out] set to true if value numbers were used
+//   pIndex - [out] the assertion used in the proof
+//
+// Returns:
+//   true if the tree's value will be non-null
+//
+// Notes:
+//   Sets "pVnBased" if the assertion is value number based. If no matching
+//    assertions are found from the table, then returns "NO_ASSERTION_INDEX."
+//
+//   If both VN and assertion table yield a matching assertion, "pVnBased"
+//   is only set and the return value is "NO_ASSERTION_INDEX."
+//
 bool Compiler::optAssertionIsNonNull(GenTree*         op,
                                      ASSERT_VALARG_TP assertions DEBUGARG(bool* pVnBased)
                                          DEBUGARG(AssertionIndex* pIndex))
@@ -3769,20 +3784,35 @@ bool Compiler::optAssertionIsNonNull(GenTree*         op,
         return true;
     }
 
-    AssertionIndex index = optAssertionIsNonNullInternal(op, assertions);
+    AssertionIndex index = optAssertionIsNonNullInternal(op, assertions DEBUGARG(pVnBased));
 #ifdef DEBUG
     *pIndex = index;
 #endif
     return index != NO_ASSERTION_INDEX;
 }
 
-/*****************************************************************************
- *  Check if a non-null assertion can be made about the input operand "op"
- *  from the set of "assertions."
- *
- */
-AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree* op, ASSERT_VALARG_TP assertions)
+//------------------------------------------------------------------------
+// optAssertionIsNonNullInternal: see if we can prove a tree's value will
+//   be non-null based on assertions
+//
+// Arguments:
+//   op - tree to check
+//   assertions  - set of live assertions
+//   pVnBased - [out] set to true if value numbers were used
+//
+// Returns:
+//   index of assertion, or NO_ASSERTION_INDEX
+//
+AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree*         op,
+                                                       ASSERT_VALARG_TP assertions DEBUGARG(bool* pVnBased))
 {
+
+#ifdef DEBUG
+    // Initialize the out param
+    //
+    *pVnBased = false;
+#endif
+
     // If local assertion prop use lcl comparison, else use VN comparison.
     if (!optLocalAssertionProp)
     {
@@ -3791,9 +3821,32 @@ AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree* op, ASSERT_VALAR
             return NO_ASSERTION_INDEX;
         }
 
-        ValueNum vn = op->gtVNPair.GetConservative();
+        // Look at both the top-level vn, and
+        // the vn we get by stripping off any constant adds.
+        //
+        ValueNum  vn     = vnStore->VNConservativeNormalValue(op->gtVNPair);
+        ValueNum  vnBase = vn;
+        VNFuncApp funcAttr;
 
-        // Check each assertion to find if we have a vn == or != null assertion.
+        while (vnStore->GetVNFunc(vnBase, &funcAttr) && (funcAttr.m_func == (VNFunc)GT_ADD))
+        {
+            if (vnStore->IsVNConstant(funcAttr.m_args[1]) && varTypeIsIntegral(vnStore->TypeOfVN(funcAttr.m_args[1])))
+            {
+                vnBase = funcAttr.m_args[0];
+            }
+            else if (vnStore->IsVNConstant(funcAttr.m_args[0]) &&
+                     varTypeIsIntegral(vnStore->TypeOfVN(funcAttr.m_args[0])))
+            {
+                vnBase = funcAttr.m_args[1];
+            }
+            else
+            {
+                break;
+            }
+        }
+
+        // Check each assertion to find if we have a vn != null assertion.
+        //
         BitVecOps::Iter iter(apTraits, assertions);
         unsigned        index = 0;
         while (iter.NextElem(&index))
@@ -3808,10 +3861,21 @@ AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree* op, ASSERT_VALAR
             {
                 continue;
             }
-            if (curAssertion->op1.vn != vn || curAssertion->op2.vn != ValueNumStore::VNForNull())
+
+            if (curAssertion->op2.vn != ValueNumStore::VNForNull())
             {
                 continue;
             }
+
+            if ((curAssertion->op1.vn != vn) && (curAssertion->op1.vn != vnBase))
+            {
+                continue;
+            }
+
+#ifdef DEBUG
+            *pVnBased = true;
+#endif
+
             return assertionIndex;
         }
     }
diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h
index a38071f31a3696..971fd105ea60af 100644
--- a/src/coreclr/jit/compiler.h
+++ b/src/coreclr/jit/compiler.h
@@ -7259,7 +7259,7 @@ class Compiler
                                           var_types        toType,
                                           ASSERT_VALARG_TP assertions);
     AssertionIndex optAssertionIsSubtype(GenTree* tree, GenTree* methodTableArg, ASSERT_VALARG_TP assertions);
-    AssertionIndex optAssertionIsNonNullInternal(GenTree* op, ASSERT_VALARG_TP assertions);
+    AssertionIndex optAssertionIsNonNullInternal(GenTree* op, ASSERT_VALARG_TP assertions DEBUGARG(bool* pVnBased));
     bool optAssertionIsNonNull(GenTree*         op,
                                ASSERT_VALARG_TP assertions DEBUGARG(bool* pVnBased) DEBUGARG(AssertionIndex* pIndex));