-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
[JIT] Codegen for combined mod/div with power of 2 constants. #8739
Comments
what if you change |
That should generate code that's similar to the code generated by the "fixed" example without requiring Some clarifications: Signed division by power of 2 generates code like: 8BC1 mov eax, ecx
8BD0 mov edx, eax
C1FA1F sar edx, 31
81E2FF1F0000 and edx, 0x1FFF
03D0 add edx, eax
8BC2 mov eax, edx
C1F80D sar eax, 13 Signed modulo power of 2 generates code like: 8BC1 mov eax, ecx
8BD0 mov edx, eax
C1FA1F sar edx, 31
81E2FF1F0000 and edx, 0x1FFF
03D0 add edx, eax
81E200E0FFFF and edx, -0x2000
2BC2 sub eax, edx In case anyone wonders why the generated code doesn't reduce to a single shift/and - that's due to the way truncation is done. Integer division truncates toward 0 so (-3 / 2) is -1. Right shift truncates toward 0 as well but due to the way negative numbers are represented it really truncates toward negative infinity so (-3 >> 1) is -2. The generated code compensates for this by adjusting the dividend when it is negative so it computes ((-3 + 1) >> 1). The adjustment happens to be similar for both division and modulus so there is some redundant code if we have both Still, using unsigned division (when the dividend is known to be positive) results in better code: ; unsigned division
8BC1 mov eax, ecx
C1E80D shr eax, 13
; unsigned modulo
8BC1 mov eax, ecx
25FF1F0000 and eax, 0x1FFF It would be nice if the JIT could detect case when the dividend is known to be positive and replace signed division with unsigned division but it's not trivial. And in the absence of interprocedural optimization it's probably not very useful. |
Closing confirmed that using unsigned long will recognize it and generate the proper code. |
You could leave this open, it may be useful to take a closer look at what the JIT can do to improve this. |
As you pointed out without a proper way to reason about the sign of the value the optimization is generally not safe to be done on long; so it doesn't make sense to keep it open. But better, lets ask people in the know about what to do about it. cc @AndyAyersMS @CarolEidt @stephentoub |
Yes, in general it's rather expensive to prove that values are positive (or within a given range). But in some case this can be done relatively cheaply by piggy-backing on range check elimination: for (int i = 0; i < a.Length; i++) {
a[i] = i / 2; // JIT already knows that i is within array bounds and thus positive
} The big question is if it's worth doing this or not. |
Power of 2 constants with divide and modulus missing optimization.
This code generates:
However you can actually rewrite that (knowing that the constant is power of 2) into:
Which will output:
That is half the bytes.
The text was updated successfully, but these errors were encountered: