@@ -4285,19 +4285,34 @@ void ValueNumStore::GetConstantBoundInfo(ValueNum vn, ConstantBoundInfo* info)
42854285 }
42864286}
42874287
4288+ // ------------------------------------------------------------------------
4289+ // IsVNPositiveInt32Constant: returns true iff vn is a known Int32 constant that is greater then 0
4290+ //
4291+ // Arguments:
4292+ // vn - Value number to query
4293+ bool ValueNumStore::IsVNPositiveInt32Constant (ValueNum vn)
4294+ {
4295+ return IsVNInt32Constant (vn) && (ConstantValue<INT32>(vn) > 0 );
4296+ }
4297+
42884298// ------------------------------------------------------------------------
42894299// IsVNArrLenUnsignedBound: Checks if the specified vn represents an expression
4290- // such as "(uint)i < (uint)len" that implies that the index is valid
4291- // (0 <= i && i < a.len).
4300+ // of one of the following forms:
4301+ // - "(uint)i < (uint)len" that implies (0 <= i < len)
4302+ // - "const < (uint)len" that implies "len > const"
4303+ // - "const <= (uint)len" that implies "len > const - 1"
42924304//
42934305// Arguments:
42944306// vn - Value number to query
42954307// info - Pointer to an UnsignedCompareCheckedBoundInfo object to return information about
42964308// the expression. Not populated if the vn expression isn't suitable (e.g. i <= len).
4297- // This enables optCreateJTrueBoundAssertion to immediatly create an OAK_NO_THROW
4309+ // This enables optCreateJTrueBoundAssertion to immediately create an OAK_NO_THROW
42984310// assertion instead of the OAK_EQUAL/NOT_EQUAL assertions created by signed compares
42994311// (IsVNCompareCheckedBound, IsVNCompareCheckedBoundArith) that require further processing.
4300-
4312+ //
4313+ // Note:
4314+ // For comparisons of the form constant <= length, this returns them as (constant - 1) < length
4315+ //
43014316bool ValueNumStore::IsVNUnsignedCompareCheckedBound (ValueNum vn, UnsignedCompareCheckedBoundInfo* info)
43024317{
43034318 VNFuncApp funcApp;
@@ -4314,6 +4329,19 @@ bool ValueNumStore::IsVNUnsignedCompareCheckedBound(ValueNum vn, UnsignedCompare
43144329 info->vnBound = funcApp.m_args [1 ];
43154330 return true ;
43164331 }
4332+ // We care about (uint)len < constant and its negation "(uint)len >= constant"
4333+ else if (IsVNPositiveInt32Constant (funcApp.m_args [1 ]) && IsVNCheckedBound (funcApp.m_args [0 ]))
4334+ {
4335+ // Change constant < len into (uint)len >= (constant - 1)
4336+ // to make consuming this simpler (and likewise for it's negation).
4337+ INT32 validIndex = ConstantValue<INT32>(funcApp.m_args [1 ]) - 1 ;
4338+ assert (validIndex >= 0 );
4339+
4340+ info->vnIdx = VNForIntCon (validIndex);
4341+ info->cmpOper = (funcApp.m_func == VNF_GE_UN) ? VNF_LT_UN : VNF_GE_UN;
4342+ info->vnBound = funcApp.m_args [0 ];
4343+ return true ;
4344+ }
43174345 }
43184346 else if ((funcApp.m_func == VNF_GT_UN) || (funcApp.m_func == VNF_LE_UN))
43194347 {
@@ -4326,6 +4354,19 @@ bool ValueNumStore::IsVNUnsignedCompareCheckedBound(ValueNum vn, UnsignedCompare
43264354 info->vnBound = funcApp.m_args [0 ];
43274355 return true ;
43284356 }
4357+ // Look for constant > (uint)len and its negation "constant <= (uint)len"
4358+ else if (IsVNPositiveInt32Constant (funcApp.m_args [0 ]) && IsVNCheckedBound (funcApp.m_args [1 ]))
4359+ {
4360+ // Change constant <= (uint)len to (constant - 1) < (uint)len
4361+ // to make consuming this simpler (and likewise for it's negation).
4362+ INT32 validIndex = ConstantValue<INT32>(funcApp.m_args [0 ]) - 1 ;
4363+ assert (validIndex >= 0 );
4364+
4365+ info->vnIdx = VNForIntCon (validIndex);
4366+ info->cmpOper = (funcApp.m_func == VNF_LE_UN) ? VNF_LT_UN : VNF_GE_UN;
4367+ info->vnBound = funcApp.m_args [1 ];
4368+ return true ;
4369+ }
43294370 }
43304371 }
43314372
0 commit comments