-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Remove bounds checks for Log2 function in FormattingHelpers.CountDigits #113790
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
f7e997a
6132b52
44c430a
cdc449d
4f61374
73d0029
7291f0c
cc95b4e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6565,6 +6565,48 @@ bool ValueNumStore::IsVNInt32Constant(ValueNum vn) | |
| return TypeOfVN(vn) == TYP_INT; | ||
| } | ||
|
|
||
| //------------------------------------------------------------------------ | ||
| // IsVNLog2: Determine if the value number is a log2 pattern, which is | ||
| // "XOR(LZCNT32(OR(X, 1), 31)" or "XOR(LZCNT64(OR(X, 1), 63))". | ||
| // | ||
| // Arguments: | ||
| // vn - the value number to analyze | ||
| // upperBound - if not null, will be set to the upper bound of the log2 pattern (31 or 63) | ||
| // | ||
| // Return value: | ||
| // true if the value number is a log2 pattern, false otherwise. | ||
| // | ||
| bool ValueNumStore::IsVNLog2(ValueNum vn, int* upperBound) | ||
| { | ||
| #if defined(FEATURE_HW_INTRINSICS) && (defined(TARGET_XARCH) || defined(TARGET_ARM64)) | ||
| int xorBy; | ||
| ValueNum op; | ||
| // First, see if it's "X ^ 31" or "X ^ 63". | ||
| if (IsVNBinFuncWithConst(vn, VNF_XOR, &op, &xorBy) && ((xorBy == 31) || (xorBy == 63))) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: This is missing handling for |
||
| { | ||
| // Drop any integer cast if any, we're dealing with [0..63] range, any integer cast is redundant. | ||
| IsVNBinFunc(op, VNF_Cast, &op); | ||
|
|
||
| #ifdef TARGET_XARCH | ||
| VNFunc lzcntFunc = (xorBy == 31) ? VNF_HWI_LZCNT_LeadingZeroCount : VNF_HWI_LZCNT_X64_LeadingZeroCount; | ||
| #else | ||
| VNFunc lzcntFunc = (xorBy == 31) ? VNF_HWI_ArmBase_LeadingZeroCount : VNF_HWI_ArmBase_Arm64_LeadingZeroCount; | ||
| #endif | ||
| // Next, see if it's "LZCNT32(X | 1)" or "LZCNT64(X | 1)". | ||
| int orBy; | ||
| if (IsVNBinFunc(op, lzcntFunc, &op) && IsVNBinFuncWithConst(op, VNF_OR, &op, &orBy) && (orBy == 1)) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just noting, that |
||
| { | ||
| if (upperBound != nullptr) | ||
| { | ||
| *upperBound = xorBy; | ||
| } | ||
| return true; | ||
| } | ||
| } | ||
| #endif | ||
| return false; | ||
| } | ||
|
|
||
| //------------------------------------------------------------------------ | ||
| // IsVNNeverNegative: Determines if the given value number can never take on a negative value | ||
| // in a signed context (i.e. when the most-significant bit represents signedness). | ||
|
|
@@ -6640,6 +6682,13 @@ bool ValueNumStore::IsVNNeverNegative(ValueNum vn) | |
| case VNF_HWI_ArmBase_Arm64_LeadingSignCount: | ||
| return VNVisit::Continue; | ||
| #endif | ||
| case VNF_XOR: | ||
| if (IsVNLog2(vn)) | ||
| { | ||
| return VNVisit::Continue; | ||
| } | ||
| break; | ||
|
|
||
| #endif // FEATURE_HW_INTRINSICS | ||
|
|
||
| default: | ||
|
|
@@ -9823,6 +9872,37 @@ bool ValueNumStore::GetVNFunc(ValueNum vn, VNFuncApp* funcApp) | |
| return false; | ||
| } | ||
|
|
||
| //---------------------------------------------------------------------------------- | ||
| // IsVNBinFunc: A specialized version of GetVNFunc that checks if the given ValueNum | ||
| // is the given VNFunc with arity 2. If so, it returns the two operands. | ||
| // | ||
| // Arguments: | ||
| // vn - The ValueNum to check. | ||
| // func - The VNFunc to check for. | ||
| // op1 - The first operand (if not null). | ||
| // op2 - The second operand (if not null). | ||
| // | ||
| // Return Value: | ||
| // true if the given vn is the given VNFunc with two operands. | ||
| // | ||
| bool ValueNumStore::IsVNBinFunc(ValueNum vn, VNFunc func, ValueNum* op1, ValueNum* op2) | ||
| { | ||
| VNFuncApp funcApp; | ||
| if (GetVNFunc(vn, &funcApp) && (funcApp.m_func == func) && (funcApp.m_arity == 2)) | ||
| { | ||
| if (op1 != nullptr) | ||
| { | ||
| *op1 = funcApp.m_args[0]; | ||
| } | ||
| if (op2 != nullptr) | ||
| { | ||
| *op2 = funcApp.m_args[1]; | ||
| } | ||
| return true; | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| bool ValueNumStore::VNIsValid(ValueNum vn) | ||
| { | ||
| ChunkNum cn = GetChunkNum(vn); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1055,6 +1055,9 @@ class ValueNumStore | |
| // Returns true if the VN represents a node that is never negative. | ||
| bool IsVNNeverNegative(ValueNum vn); | ||
|
|
||
| // Returns true if the VN represents BitOperations.Log2 pattern | ||
| bool IsVNLog2(ValueNum vn, int* upperBound = nullptr); | ||
|
|
||
| typedef SmallHashTable<ValueNum, bool, 8U> CheckedBoundVNSet; | ||
|
|
||
| // Returns true if the VN is known or likely to appear as the conservative value number | ||
|
|
@@ -1408,6 +1411,38 @@ class ValueNumStore | |
| // the function application it represents; otherwise, return "false." | ||
| bool GetVNFunc(ValueNum vn, VNFuncApp* funcApp); | ||
|
|
||
| // Returns "true" iff "vn" is a function application of the form "func(op1, op2)". | ||
| bool IsVNBinFunc(ValueNum vn, VNFunc func, ValueNum* op1 = nullptr, ValueNum* op2 = nullptr); | ||
|
|
||
| // Returns "true" iff "vn" is a function application of the form "func(op, cns)" | ||
| // the cns can be on the left side if the function is commutative. | ||
| template <typename T> | ||
| bool IsVNBinFuncWithConst(ValueNum vn, VNFunc func, ValueNum* op, T* cns) | ||
|
Comment on lines
+1416
to
+1421
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: Other functions in this class seem to write out Feel free to ignore or address as part of a separate PR. |
||
| { | ||
| T opCns; | ||
| ValueNum op1, op2; | ||
| if (IsVNBinFunc(vn, func, &op1, &op2)) | ||
| { | ||
| if (IsVNIntegralConstant(op2, &opCns)) | ||
| { | ||
| if (op != nullptr) | ||
| *op = op1; | ||
| if (cns != nullptr) | ||
| *cns = opCns; | ||
| return true; | ||
| } | ||
| else if (VNFuncIsCommutative(func) && IsVNIntegralConstant(op1, &opCns)) | ||
| { | ||
| if (op != nullptr) | ||
| *op = op2; | ||
| if (cns != nullptr) | ||
| *cns = opCns; | ||
| return true; | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| // Returns "true" iff "vn" is a valid value number -- one that has been previously returned. | ||
| bool VNIsValid(ValueNum vn); | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NOTE: ideally, we should have handled XOR/OR/HWINTRINSIC all separately for GetRange, but it seems that it has no diffs outside of Log2 pattern, so I decided to just do an ad-hoc Log2 matching.