# Functions for low-level arithmetic

**URL:** <https://discourse.julialang.org/t/functions-for-low-level-arithmetic/2925>\
**Category:** Internals & Design\
**Created:** [March 28, 2017, 1:02pm UTC](https://discourse.julialang.org/t/functions-for-low-level-arithmetic/2925 "2017-03-28T13:02:47Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [March 28, 2017, 1:02pm UTC](https://discourse.julialang.org/t/functions-for-low-level-arithmetic/2925/1 "2017-03-28T13:02:47Z")

</div>

I was wondering if there were any way to get access to the the sorts of assembly instructions like unsigned multiply of UInt64 \* UInt64 producing UInt128 (for 64-bit platforms), or UInt32 \* UInt32 producing UInt64 (for 32-bit platforms),  
or UInt64 \* UInt64 + UInt64 producing UInt128 (which also cannot cause an overflow).

These sorts of instructions are very useful for writing basic arithmetic packages efficiently, without having to resort to assembly language.

---

<div class="post-metadata">

**Author:** ![lobingera](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lobingera/32/211_2.png) [@lobingera](https://discourse.julialang.org/u/lobingera)\
**Post date:** [March 28, 2017, 1:05pm UTC](https://discourse.julialang.org/t/functions-for-low-level-arithmetic/2925/2 "2017-03-28T13:05:10Z")

</div>

[http://llvm.org/docs/LangRef.html#add-instruction](http://llvm.org/docs/LangRef.html#add-instruction)

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [March 28, 2017, 1:12pm UTC](https://discourse.julialang.org/t/functions-for-low-level-arithmetic/2925/3 "2017-03-28T13:12:58Z")

</div>

I’m looking for multiplication, not plain addition, although for addition, you really want to be able to have  
`i64 + i64 -> i64, carry bit`, and `i64 + i64 + carry -> i64, carry`

From the LLVM documentation, it seems that they don’t support the low level instructions, which surprises me a bit:  
“If a full product (e.g. i32 \* i32 → i64) is needed, the operands should be sign-extended or zero-extended as appropriate to the width of the full product.”

Also, I was asking about if these operations were accessible from Julia - I don’t know how you’d go about inserting LLVM IR into a Julia program.

---

<div class="post-metadata">

**Author:** ![lobingera](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lobingera/32/211_2.png) [@lobingera](https://discourse.julialang.org/u/lobingera)\
**Post date:** [March 28, 2017, 1:58pm UTC](https://discourse.julialang.org/t/functions-for-low-level-arithmetic/2925/4 "2017-03-28T13:58:33Z")

</div>

[http://docs.julialang.org/en/stable/stdlib/c/#llvm-interface](http://docs.julialang.org/en/stable/stdlib/c/#llvm-interface)

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [March 28, 2017, 5:05pm UTC](https://discourse.julialang.org/t/functions-for-low-level-arithmetic/2925/5 "2017-03-28T17:05:48Z")

</div>

Thanks, but that doesn’t seem to help, since the low-level instructions I’m looking for don’t seem to be present in the LLVM IR.

---

<div class="post-metadata">

**Author:** ![vchuravy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vchuravy/32/8_2.png) [@vchuravy](https://discourse.julialang.org/u/vchuravy)\
**Post date:** [March 29, 2017, 4:28am UTC](https://discourse.julialang.org/t/functions-for-low-level-arithmetic/2925/6 "2017-03-29T04:28:34Z")

</div>

The `mul` instruction in LLVM [LLVM Language Reference Manual — LLVM 18.0.0git documentation](http://llvm.org/docs/LangRef.html#mul-instruction) has the following note:

> If a full product (e.g. i32 \* i32 → i64) is needed, the operands should be sign-extended or zero-extended as appropriate to the width of the full product.

So the first thing to test is if the intel llvm backend correctly detects this pattern:

```julia
%a = zext i32 %0 to i64;
%b = zext i32 %0 to i64;
%res = mul i64 %a, %b;
ret i64 %res;

```

If the backend does **not** correctly detect the pattern you can either fix that in LLVM or use inline assembly in the LLVM IR [LLVM Language Reference Manual — LLVM 18.0.0git documentation](http://llvm.org/docs/LangRef.html#inline-assembler-expressions).
