diff --git a/src/coreclr/jit/rangecheck.cpp b/src/coreclr/jit/rangecheck.cpp index a8f9ecd4e4a3fd..85953433c066aa 100644 --- a/src/coreclr/jit/rangecheck.cpp +++ b/src/coreclr/jit/rangecheck.cpp @@ -845,6 +845,42 @@ Range RangeCheck::GetRangeFromAssertionsWorker( } result = RangeOps::EvalRelop(cmpOper, isUnsigned, r1, r2); + + // Example: "(uint)(length - 4) > (uint)length" folds to false when + // length >= 4 (the typical Slice(length - cns) bounds check). + if (!result.IsSingleValueConstant()) + { + ValueNum op1VN = funcApp.m_args[0]; + ValueNum op2VN = funcApp.m_args[1]; + ValueNum addOpVN; + int addCns; + + if (comp->vnStore->IsVNBinFuncWithConst(op1VN, VNF_ADD, &addOpVN, &addCns) && + (addOpVN == op2VN) && (addCns < 0) && (addCns > INT32_MIN)) + { + if (r2.LowerLimit().IsConstant() && (r2.LowerLimit().GetConstant() >= -addCns)) + { + // ADD(A, K) < A is proven (both signed and unsigned). + switch (cmpOper) + { + case GT_LT: + case GT_LE: + case GT_NE: + result = Range(Limit(Limit::keConstant, 1)); + break; + + case GT_GT: + case GT_GE: + case GT_EQ: + result = Range(Limit(Limit::keConstant, 0)); + break; + + default: + break; + } + } + } + } } break; } diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp index df26e2029421bf..f5584a2d6f3735 100644 --- a/src/coreclr/jit/valuenum.cpp +++ b/src/coreclr/jit/valuenum.cpp @@ -5372,10 +5372,26 @@ ValueNum ValueNumStore::EvalUsingMathIdentity(var_types typ, VNFunc func, ValueN if (!ovf) { + // x - (x + a) == -a + // x - (a + x) == -a + ValueNum arg1Op1; + ValueNum arg1Op2; + if (IsVNBinFunc(arg1VN, VNF_ADD, &arg1Op1, &arg1Op2)) + { + if (arg1Op1 == arg0VN) + { + return VNForFunc(typ, VNF_NEG, arg1Op2); + } + if (arg1Op2 == arg0VN) + { + return VNForFunc(typ, VNF_NEG, arg1Op1); + } + } + // (x + a) - x == a // (a + x) - x == a VNFuncApp add; - if (GetVNFunc(arg0VN, &add) && (add.m_func == (VNFunc)GT_ADD)) + if (GetVNFunc(arg0VN, &add) && (add.m_func == VNF_ADD)) { if (add.m_args[0] == arg1VN) return add.m_args[1]; @@ -5387,7 +5403,7 @@ ValueNum ValueNumStore::EvalUsingMathIdentity(var_types typ, VNFunc func, ValueN // (x + a) - (b + x) == a - b // (a + x) - (b + x) == a - b VNFuncApp add2; - if (GetVNFunc(arg1VN, &add2) && (add2.m_func == (VNFunc)GT_ADD)) + if (GetVNFunc(arg1VN, &add2) && (add2.m_func == VNF_ADD)) { for (int a = 0; a < 2; a++) { @@ -5395,7 +5411,7 @@ ValueNum ValueNumStore::EvalUsingMathIdentity(var_types typ, VNFunc func, ValueN { if (add.m_args[a] == add2.m_args[b]) { - return VNForFunc(typ, (VNFunc)GT_SUB, add.m_args[1 - a], add2.m_args[1 - b]); + return VNForFunc(typ, VNF_SUB, add.m_args[1 - a], add2.m_args[1 - b]); } } }