# Is there a way to get \`mul\_hi\`/\`umulh\`?

**URL:** https://discourse.julialang.org/t/is-there-a-way-to-get-mul-hi-umulh/112109
**Category:** General Usage
**Created:** [March 25, 2024, 10:28pm UTC](https://discourse.julialang.org/t/is-there-a-way-to-get-mul-hi-umulh/112109 "2024-03-25T22:28:18Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![Lilith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lilith/32/27492_2.png) [@Lilith](https://discourse.julialang.org/u/Lilith)
#### Post date: [March 25, 2024, 10:28pm UTC](https://discourse.julialang.org/t/is-there-a-way-to-get-mul-hi-umulh/112109/1 "2024-03-25T22:28:18Z")

</div>

Similar to (identical to) [`mul_hi` in Julia?](https://discourse.julialang.org/t/mul-hi-in-julia/14235), is there a way of accessing the high bits of a product between two bit integers?

I want a function `mul_hi` such that `widen(mul_hi(x, y)) << 8sizeof(T) + x*y == widemul(x,y)` for `x::T`, `y::T`, and I want it to use the native `umulh` instruction where available.

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [March 25, 2024, 10:34pm UTC](https://discourse.julialang.org/t/is-there-a-way-to-get-mul-hi-umulh/112109/2 "2024-03-25T22:34:05Z")

</div>

I don’t believe so. It probably would be smart to add. Right now, we mostly rely on LLVM figuring it out from `widemul` where necessar.

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [March 26, 2024, 1:18pm UTC](https://discourse.julialang.org/t/is-there-a-way-to-get-mul-hi-umulh/112109/3 "2024-03-26T13:18:46Z")

</div>

You might be able to invoke a LLVM intrinsic via `llvmcall`. Do you know of language with mul\_hi? We can reverse engineer it from there.

---

<div class="post-metadata">

### Author: ![Lilith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lilith/32/27492_2.png) [@Lilith](https://discourse.julialang.org/u/Lilith)
#### Post date: [March 26, 2024, 1:32pm UTC](https://discourse.julialang.org/t/is-there-a-way-to-get-mul-hi-umulh/112109/4 "2024-03-26T13:32:16Z")

</div>

That works for 64-bit, but not 128-bit.

```julia
ulia> function mul_hi(x::T, y::T) where T <: Base.BitInteger
           xy = widemul(x, y)
           (xy >> 8sizeof(T)) % T
       end
mul_hi (generic function with 2 methods)

julia> @b mul_hi($(rand(UInt64)), $(rand(UInt64)))
1.982 ns

julia> @b mul_hi($(rand(UInt128)), $(rand(UInt128)))
193.885 ns (12 allocs: 224 bytes)

julia> @code_native mul_hi(rand(UInt64), rand(UInt64))
        .text
        .file "mul_hi"
        .globl julia_mul_hi_33966 // -- Begin function julia_mul_hi_33966
        .p2align 2
        .type julia_mul_hi_33966,@function
julia_mul_hi_33966: // @julia_mul_hi_33966
; Function Signature: mul_hi(UInt64, UInt64)
; ┌ @ REPL[264]:1 within `mul_hi`
// %bb.0: // %top
; │ @ REPL[264] within `mul_hi`
        //DEBUG_VALUE: mul_hi:x <- $x0
        //DEBUG_VALUE: mul_hi:x <- $x0
        //DEBUG_VALUE: mul_hi:y <- $x1
        //DEBUG_VALUE: mul_hi:y <- $x1
        stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
        mov x29, sp
; │ @ REPL[264]:3 within `mul_hi`
; │┌ @ int.jl:534 within `>>` @ int.jl:528
        umulh x0, x1, x0
; │└
; │┌ @ int.jl:544 within `rem`
        ldp x29, x30, [sp], #16 // 16-byte Folded Reload
        ret
.Lfunc_end0:
        .size julia_mul_hi_33966, .Lfunc_end0-julia_mul_hi_33966
; └└
                                        // -- End function
        .section ".note.GNU-stack","",@progbits

```

[Julia feature request](https://github.com/JuliaLang/julia/issues/53855)

---

<div class="post-metadata">

### Author: ![Lilith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lilith/32/27492_2.png) [@Lilith](https://discourse.julialang.org/u/Lilith)
#### Post date: [March 26, 2024, 1:42pm UTC](https://discourse.julialang.org/t/is-there-a-way-to-get-mul-hi-umulh/112109/5 "2024-03-26T13:42:24Z")

</div>

After a quick look I was unable to find an LLVM intrinsic for this.

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [March 28, 2024, 4:12am UTC](https://discourse.julialang.org/t/is-there-a-way-to-get-mul-hi-umulh/112109/6 "2024-03-28T04:12:54Z")

</div>

The main reference I see for an existing `mul_hi` is from OpenCL:

[https://registry.khronos.org/OpenCL/sdk/1.1/docs/man/xhtml/mul\_hi.html](https://registry.khronos.org/OpenCL/sdk/1.1/docs/man/xhtml/mul_hi.html)

I see some references to `smul_lohi` and `umul_lohi` in the the LLVM documentation:

[https://llvm.org/doxygen/namespacellvm\_1\_1ISD.html#a22ea9cec080dd5f4f47ba234c2f59110a1354c6f8508d6cd697dc89a5d9a52dfd](https://llvm.org/doxygen/namespacellvm_1_1ISD.html#a22ea9cec080dd5f4f47ba234c2f59110a1354c6f8508d6cd697dc89a5d9a52dfd)
