Skip to content

[API Proposal]: Math.MulHigh #68207

Closed as not planned
Closed as not planned

Description

@saucecontrol

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

Activity

  1. added
    api-suggestionEarly API idea and discussion, it is NOT ready for implementation
    on Apr 19, 2022
  2. ghost added
    untriagedNew issue has not been triaged by the area owner
    on Apr 19, 2022
  3. added
    needs-further-triageIssue has been initially triaged, but needs deeper consideration or reconsideration
    and removed
    untriagedNew issue has not been triaged by the area owner
    on Jul 15, 2022
  4. added this to the Future milestone on Jul 15, 2022
  5. Daniel-Svensson commented on Jun 1, 2025

    @Daniel-Svensson
    Contributor

    It sounds like a reasonable suggestion, MultiplyHigh seems a more promising name since there are now an method with that name for arm.

    However the BigMul method should hopefully be proper optimized soon, making this less urgent

    I wonder if the team would prefer to have the method placed on the types themselvs, such as int.MultiplyHigh.
    It would be nice if this woud get an api-review

  6. tannergooding commented on Jun 18, 2025

    @tannergooding
    Member

    I think it would be better if we could just correctly optimize BigMul where the upper bits aren't used.

    If we were to expose MultiplyHigh, then it would need to be directly on the primitive types (all of the ones exposing BigMul at the very least). But, I don't really see the need or benefit when most hardware requires computing both halves anyways and we could ideally just pattern match to get the existing APIs to behave correctly.

  7. Daniel-Svensson commented on Jun 18, 2025

    @Daniel-Svensson
    Contributor

    Just to mention I have an open PR #115966 that solves the codegen issue for x64 , it was already very good for ARM64.

  8. tannergooding commented on Jun 19, 2025

    @tannergooding
    Member

    Going to close this for the reasons given above.

  9. locked and limited conversation to collaborators on Jul 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-suggestionEarly API idea and discussion, it is NOT ready for implementationarea-System.Numericsneeds-further-triageIssue has been initially triaged, but needs deeper consideration or reconsideration

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions