Skip to content
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 Proposal]: Math.MulHigh #68207

Open
saucecontrol opened this issue Apr 19, 2022 · 1 comment
Open

[API Proposal]: Math.MulHigh #68207

saucecontrol opened this issue Apr 19, 2022 · 1 comment
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Numerics needs-further-triage Issue has been initially triaged, but needs deeper consideration or reconsideration
Milestone

Comments

@saucecontrol
Copy link
Member

saucecontrol commented Apr 19, 2022

Background and motivation

On Arm64, there is already a MultiplyHigh intrinsic that returns only the high part of an integer multiply. On x86/x64, mul and imul calculate the high part and low part at the same time can return the results in 2 registers, however there is no intrinsic that gives access to the high part of the result.

At present, the only way to get the high part of an integer multiply on x86/x64 is to use Math.BigMul and discard the low part of the result. BigMul is not currently optimized, although there is an open proposal for a multiply intrinsic that returns both halves of the result in a tuple #58263

I would like to propose a cross-platform way of accessing this functionality, as Math.MulHigh.

API Proposal

namespace System;

public static class Math
{
    public static int MulHigh(int left, int right);
    public static uint MulHigh(uint left, uint right);

    public static long MulHigh(long left, long right);
    public static ulong MulHigh(ulong left, ulong right);
}

API Usage

ulong hi = Math.MulHigh(a, b);

Alternative Designs

Most C compilers recognize a large multiply followed by a shift right as a smaller multiply high. Something like:

int64 hi = (int64)((int128)int64 * int64) >> 64);
int32 hi = (int32)((int64)int32 * int32 >> 32);

With the new Int128 type coming to .NET, this could be a possibililty.

#58263 proposes a tuple-returning multiply that would return both halves of the result. It would be possible to simply ignore the lower half as long as JIT could optimize this.

Or Math.BigMul could be optimized to use mul/imul and JIT could be made to recognize a discard of the low part parameter of , such that

ulong hi = Math.BigMul(a, b, out _);

would generate optimal code.

Risks

No response

@saucecontrol saucecontrol added the api-suggestion Early API idea and discussion, it is NOT ready for implementation label Apr 19, 2022
@dotnet-issue-labeler dotnet-issue-labeler bot added area-System.Numerics untriaged New issue has not been triaged by the area owner labels Apr 19, 2022
@ghost
Copy link

ghost commented Apr 19, 2022

Tagging subscribers to this area: @dotnet/area-system-numerics
See info in area-owners.md if you want to be subscribed.

Issue Details

Background and motivation

On Arm64, there is already a MultiplyHigh intrinsic that returns only the high part of an integer multiply. On x86/x64, mul and imul calculate the high part and low part at the same time can return the results in 2 registers, however there is no intrinsic that gives access to the high part of the result.

At present, the only way to get the high part of an integer multiply on x86/x64 is to use Math.BigMul and discard the low part of the result. BigMul is not currently optimized, although there is an open proposal for a multiply intrinsic that returns both halves of the result in a tuple #58263

I would like to propose a cross-platform way of accessing this functionality, as Math.MulHigh.

API Proposal

namespace System;

public static class Math
{
    public static int MulHigh(int left, int right);
    public static uint MulHigh(uint left, uint right);

    public static long MulHigh(long left, long right);
    public static ulong MulHigh(ulong left, ulong right);
}

API Usage

ulong hi = Math.MulHigh(a, b);

Alternative Designs

Most C compilers recognize a large multiply followed by a shift right as a smaller multiply high, e.g. (int64)((int128)int64 * in64) >> 64) or (int32)((int64)int32 * in32 >> 32). With the new Int128 type coming to .NET, this could be a possibililty.

#58263 proposes a tuple-returning multiply that would return both halves of the result. It would be possible to simply ignore the lower half as long as JIT could optimize this.

Or Math.BigMul could be optimized to use mul/imul and JIT could be made to recognize a discard of the low part parameter of , such that

ulong hi = Math.BigMul(a, b, out _);

would generate optimal code.

Risks

No response

Author: saucecontrol
Assignees: -
Labels:

api-suggestion, area-System.Numerics, untriaged

Milestone: -

@tannergooding tannergooding added needs-further-triage Issue has been initially triaged, but needs deeper consideration or reconsideration and removed untriaged New issue has not been triaged by the area owner labels Jul 15, 2022
@tannergooding tannergooding added this to the Future milestone Jul 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Numerics needs-further-triage Issue has been initially triaged, but needs deeper consideration or reconsideration
Projects
None yet
Development

No branches or pull requests

2 participants