-
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
API: long Math.BigMul(long, long, out long) #31184
Comments
@benaadams it already exists in System.Runtime.Intrinsics.BMI2: https://github.com/dotnet/coreclr/blob/master/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi2.cs#L48 |
Technically MultiplyNoFlags is different ( |
It's also supported in Mono-LLVM (and doesn't use mulx directly - instead, it uses Int128): mono/mono#17031 |
Nice! |
@benaadams, is this not something you still want more generally (and on hardware without BMI2 support)?
There is a proposal to expose |
On example is using the high 64 bits from a 64bit * 64bit => 128bit multiplication and then could avoid modulo from Dictionary by adding a long to it: ulong modAdjust = ...; // 0xFFFFFFFFFFFFFFFFuL / prime + 1
uint FastMod(uint hash, uint prime)
{
ulong lowbits = modAdjust * hash;
return Math.MultHigh(lowbits, prime);
} |
Updated the dictionary PR to use this approach dotnet/coreclr#27299 (comment) |
If we mirrored the C/C++ intrinsics, they would be something like: long MultiplyHigh(long left, long right);
long Multiply128(long left, long right, out long highProduct); |
Ah, that's basically what is proposed in the OP, but with different names and I just misread them. I'm not a fan of shortening So, for consistency, I think sticking with Once we come up with some decent names, I think we can mark as I would think it would also be desirable to expose the following for parity: int MultiplyHigh(int left, int right); // or w/e name is decided |
Updated. A side point... Bmi is low rather than high ulong MultiplyNoFlags(ulong left, ulong right, ulong* low) |
Ah, right. We changed that in https://github.com/dotnet/corefx/issues/33615 due to customer feedback and ease of implementation in the JIT (it also makes it a natural extension to |
Happy with either for the |
If you could update so that it matches |
Done :) |
Manual multiply high is now being used for Dictionary Which looks like (uint)((((ulong)(uint)left * right >> 32) + (left >> 32) * right) >> 32) When ideally it would be (uint)Math.MultiplyHigh(left, right) |
Do we need really need the |
Suppose not as discards make it not very onerous ulong high = BigMul(a, b, out _); |
Naming nit: |
I had the same initial concern, but it matches the naming (and effective functionality) of the existing |
Naming is from the prior api Updated summary to drop MultiplyHigh |
There is some related discussion in #27292 |
namespace System
{
public partial class Math
{
public ulong BigMul(ulong a, ulong b, out ulong low);
public long BigMul(long a, long b, out long low);
}
} |
Implemented in #35975 |
API Shape
To return 128 bit result (as per
long BigMul(int a, int b)
)Use case
Manual multiply high is now being used for Dictionary
Which looks like
When ideally it would be
Other langs
While it is what the asm does (i.e.
RDX:RAX ← RAX ∗ SRC
) the apis either use a 128bit value or the split pair.MSVC:
__int64 _mul128(__int64 Multiplier, __int64 Multiplicand, __int64 *HighProduct) __int64 __mulh(__int64 a, __int64 b)
Others use
*
overloading on a__uint128_t
typeThe text was updated successfully, but these errors were encountered: