-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Simplify/optimize Int128 comparison operators #101848
Simplify/optimize Int128 comparison operators #101848
Conversation
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.
Code is purely simpler and is still correct
That being said, it's worth noting that this simplification doesn't buy much and the real optimization requires some JIT work so we can simply emit a cmp; sbb; setcc
sequence instad.
{ | ||
return IsNegative(left); | ||
} | ||
return ((long)left._upper < (long)right._upper) |
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.
A comment (in the code) explaining why this is valid would be beneficial.
Actually brute forcing this for some struct S16 { byte _lower; byte _upper; }
is pretty trivial to do, but so is describing why this works out given the two's complement representation. -- Notably this comes down to the fact that all negative values have the sign bit set, so if lhs.upper < rhs.upper
in signed form, then either lhs/rhs have different signs, and the single comparison was sufficient or they have the same sign and the same was true.
There may be other optimizations available here as well... In particular, comparisons x cmp y
in general are done as if x - y
and then setting CPU flags, without actually producing the result. That general premise is why the "most optimal" pattern is actually cmp lower; sbb upper; setcc
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.
I tried my best documenting it with comments.
Thanks for feedback. And indeed, that approach would be the most optimal. But I had a hunch it sadly is not really possible in C# at the moment. |
* Optimize In128 comparison operators * Document how Int128 comparison operators work
We can remove a some branches in comparison operators for
Int128
by using signed comparison for upper 64-bit values.Maybe this approach was already considered but not chosen, in that case I will close the PR.
Also added some test cases for some better coverage on said operators.
It was hard to benchmark any performance gain because (getting ZeroMeasurement) so I had to run the operators inside a loop.
Link to benchmark source code here.
Below are benchmarks for
>
operator (other operators gives similar results):In some cases it seems we get ~5% perf improvements.
Code (and codegen) is more compact. sharplab.