Remove bounds checks for Log2 function in FormattingHelpers.CountDigits#113790
Remove bounds checks for Log2 function in FormattingHelpers.CountDigits#113790EgorBo merged 8 commits intodotnet:mainfrom
Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR removes bounds checks and unsafe array access in the Log2-based digit lookup in FormattingHelpers.CountDigits, improving both performance and clarity.
- Replaces Unsafe.Add pointer arithmetic with direct array indexing for the ulong-based digit lookup.
- Applies the same change for the uint-based computation using a lookup table.
Files not reviewed (3)
- src/coreclr/jit/rangecheck.cpp: Language not supported
- src/coreclr/jit/valuenum.cpp: Language not supported
- src/coreclr/jit/valuenum.h: Language not supported
|
@jakobbotsch @dotnet/jit-contrib PTAL - removes unsafe array access from two places. Just a couple of diffs, but, hopefully, this introduces more convenient helpers to do pattern matching on top of VNs. the GetVNFunc patter is quite verbose |
| Range RangeCheck::ComputeRangeForBinOp(BasicBlock* block, GenTreeOp* binop, bool monIncreasing DEBUGARG(int indent)) | ||
| { | ||
| assert(binop->OperIs(GT_ADD, GT_AND, GT_RSH, GT_RSZ, GT_LSH, GT_UMOD, GT_MUL)); | ||
| assert(binop->OperIs(GT_ADD, GT_XOR, GT_AND, GT_RSH, GT_RSZ, GT_LSH, GT_UMOD, GT_MUL)); |
There was a problem hiding this comment.
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.
| 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.
nit: This is missing handling for X86Base_BitScanReverse which is used for R2R and NAOT, since LZCNT isn't baseline.
| #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.
Just noting, that X | 1 isn't required if we know that X != 0, but its probably not necessary to handle.
| 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) |
There was a problem hiding this comment.
Nit: Other functions in this class seem to write out Binary in full (e.g. EvalMathFuncBinary above).
Feel free to ignore or address as part of a separate PR.
|
@EgorBo, can this be merged? |
Yeah, I wanted to generalize the jit part a bit, but I think I'll merge as is, let me check again |
|
/ba-g same issue as #116041 |
Closes #79257
And replaces unsafe array access in FormattingHelpers.CountDigits.cs
Example:
Was:
Now: