@@ -4285,19 +4285,34 @@ void ValueNumStore::GetConstantBoundInfo(ValueNum vn, ConstantBoundInfo* info)
4285
4285
}
4286
4286
}
4287
4287
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
+
4288
4298
// ------------------------------------------------------------------------
4289
4299
// 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"
4292
4304
//
4293
4305
// Arguments:
4294
4306
// vn - Value number to query
4295
4307
// info - Pointer to an UnsignedCompareCheckedBoundInfo object to return information about
4296
4308
// 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
4298
4310
// assertion instead of the OAK_EQUAL/NOT_EQUAL assertions created by signed compares
4299
4311
// (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
+ //
4301
4316
bool ValueNumStore::IsVNUnsignedCompareCheckedBound (ValueNum vn, UnsignedCompareCheckedBoundInfo* info)
4302
4317
{
4303
4318
VNFuncApp funcApp;
@@ -4314,6 +4329,19 @@ bool ValueNumStore::IsVNUnsignedCompareCheckedBound(ValueNum vn, UnsignedCompare
4314
4329
info->vnBound = funcApp.m_args [1 ];
4315
4330
return true ;
4316
4331
}
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
+ }
4317
4345
}
4318
4346
else if ((funcApp.m_func == VNF_GT_UN) || (funcApp.m_func == VNF_LE_UN))
4319
4347
{
@@ -4326,6 +4354,19 @@ bool ValueNumStore::IsVNUnsignedCompareCheckedBound(ValueNum vn, UnsignedCompare
4326
4354
info->vnBound = funcApp.m_args [0 ];
4327
4355
return true ;
4328
4356
}
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
+ }
4329
4370
}
4330
4371
}
4331
4372
0 commit comments