diff --git a/src/coreclr/jit/rangecheck.cpp b/src/coreclr/jit/rangecheck.cpp index d7426258011e25..dca63fb6efdb2a 100644 --- a/src/coreclr/jit/rangecheck.cpp +++ b/src/coreclr/jit/rangecheck.cpp @@ -1017,14 +1017,27 @@ void RangeCheck::MergeEdgeAssertions(Compiler* comp, ValueNum addOpVN; int addOpCns; if (comp->vnStore->IsVNBinFuncWithConst(curAssertion.GetOp1().GetVN(), VNF_ADD, &addOpVN, &addOpCns) && - (addOpVN == normalLclVN) && (addOpCns >= 0)) + (addOpVN == normalLclVN)) { - cmpOper = GT_LT; - limit = Limit(Limit::keBinOpArray, preferredBoundVN, -addOpCns); - isUnsigned = false; - // The comparison being unsigned may also hint that the lower bound is -CNS1, but it's - // unlikely to be useful, so we ignore it for now. The whole thing will work only if some other - // assertion proves that the normalLclVN's lower bound is non-negative. + if (addOpCns >= 0) + { + cmpOper = GT_LT; + limit = Limit(Limit::keBinOpArray, preferredBoundVN, -addOpCns); + isUnsigned = false; + } + else if (addOpCns > INT32_MIN) + { + // (normalLclVN + negConst) u< bound, with bound non-negative. + // Since the comparison is unsigned, (normalLclVN + negConst) must not have wrapped, + // which means normalLclVN >= -negConst. + cmpOper = GT_GE; + limit = Limit(Limit::keConstant, -addOpCns); + isUnsigned = false; + } + else + { + continue; + } } else { @@ -2013,8 +2026,18 @@ Range RangeCheck::ComputeRange(BasicBlock* block, GenTree* expr, bool monIncreas } else if (expr->OperIs(GT_ARR_LENGTH)) { - // Better than keUnknown - range = Range(Limit(Limit::keConstant, 0), Limit(Limit::keConstant, CORINFO_Array_MaxLength)); + ValueNum arrLenVN = m_compiler->optConservativeNormalVN(expr); + if ((arrLenVN != ValueNumStore::NoVN) && (arrLenVN == m_preferredBound)) + { + // If the ARR_LENGTH VN matches the bounds check's length VN, represent it symbolically + // so the PHI merge can combine it with other symbolic ranges referencing the same bound. + range = Range(Limit(Limit::keConstant, 0), Limit(Limit::keBinOpArray, arrLenVN, 0)); + } + else + { + // Better than keUnknown + range = Range(Limit(Limit::keConstant, 0), Limit(Limit::keConstant, CORINFO_Array_MaxLength)); + } } else {