-
Notifications
You must be signed in to change notification settings - Fork 2.7k
JIT: Optimize simple range checks with uint
hack
#27480
Conversation
Does this include |
@benaadams good question, unfortunately not 🙁 int Case1(int i, Span<int> array)
{
if (i < 0 || i >= array.Length)
throw new ArgumentException();
return array[i];
}
But probably I somehow can figure out that that |
|
Thank you for your contribution. As announced in dotnet/coreclr#27549 this repository will be moving to dotnet/runtime on November 13. If you would like to continue working on this PR after this date, the easiest way to move the change to dotnet/runtime is:
|
Just a heads up that I don't think the code gen optimization listed at the very beginning of this issue is valid. That is, I believe it produces observable side effects. In the "before" code, if i is negative and array is null, control will flow to the |
Yes, it does. And that's not the only issue in this PR. |
Thank you for your contribution. As announced in #27549 the dotnet/runtime repository will be used going forward for changes to this code base. Closing this PR as no more changes will be accepted into master for this repository. If you’d like to continue working on this change please move it to dotnet/runtime. |
JIT-level optimization for checks in #27462.
I decided to run the optimization twice before and after CSE.
Before CSE run helps to remove bound checks but can't really optimize the constant-range case due to possible CSE candidates (if I check both conditional nodes for
IsCSECandidate
and don't run it after CSE phase I'll lose ~1000 bytes in the jit-diff).If I remove the
weight == 0
check, the jit-diff becomes -3858 but in theory can decrease performance in some cases, e.g.:if
i < 10
is mostly true - it's better to leave thisif
as is. (Perhaps I should check the first condition for "is likely to be true" instead of zero weight for the target block)UPD: It seems, C++ compilers don't really care: https://godbolt.org/z/D9YRVQ (
add
has1
latency on most CPUs)Current jit-diff:
https://gist.github.com/EgorBo/f4a21c16e350e9ae3cd9338ef683526a
(NOTE: the diff can be a lot bigger if we remove hundreds of
uint
hacks already exist in the BCL)Let me know if you think this opt is a good idea and I'll add tests (or feel free to close if you are ok with the managed-side fix in #27462).
/cc: @jkotas @mikedn @benaadams
UPD: Can be implemented:
return i < 10 || i > 100;
won't be optimized because it needs something like "expand BBJ_RETURN blocks to BBJ_COND" kind of de-optimization, see Expand BBJ_RETURN blocks with bool conditions #27167Unsafe.Assume
kind of API 🙂if(index == 0 || index > 1)
->if(index >= 1)
if (('A' <= c) && (c <= 'Z'))