<p>I'm writing a language frontend for LLVM, and I noticed that the IR docs say that integers of (almost) any width can be used without limit. I presume this to mean that LLVM or its backends convert numbers with a width larger than the target's width into multiple chunks during execution. I also see that the docs make no mention of not using 64-bit ints on 32-bit platforms, since the backends presumably split 64-bit ints in half in that case. However, this splitting might incur a runtime cost of some sort. So, how big is the performance cost (if any; maybe LLVM can optimize this away in some situations) of making my frontend emit 64-bit integers regardless of the width of the target platform, as opposed to having it only emit 32-bit ones on 32-bit platforms and only emit 64-bit ones on 64-bit platforms? (The performance cost will of course vary by context; I'm asking if it is consistently large enough to warrant making the compiler check for it.)</p>

<compilers><integers><llvm>
What, if any, runtime cost is incurred by using 64-bit ints on 32-bit platforms in LLVM?
CC BY-SA 4.0
2023-09-27T15:39:35.160Z
I think this question needs some clarification. Runtime cost in contrast to what? Lower bitcounts in the same architecture or 64 bits in the 64 bit equivalent platform? This compiler explorer example https://godbolt.org/z/rE1YzE948 seems to imply it depends on use case as well, since adding is just one more instruction, yet 64bit multiplication more than doubles the instruction count of 32bit multiplication.
kouta-kun
CC BY-SA 4.0
2023-09-28T00:47:45.837Z
Note that word size may not be the same for everything on some architectures. Some processors have supported (some) 64-bit integer operations while still only supporting 32-bit addressing for instance.
jcaron
CC BY-SA 4.0
2023-09-28T11:27:55.740Z
@jcaron Huh, I didn't know that. Interesting! I wonder if backends for those processors take advantage of that fact.
Ginger
CC BY-SA 4.0
2023-09-28T11:38:34.293Z
@Ginger one issue in some cases is that such features may vary from one processor to the next in the same architecture, so either you have to target a sub-family of processors, or the decision must be made at runtime, which is a lot more likely in libraries than in the generic code generated by the compiler. Some processing-heavy libraries (e.g. crypto) will have lots of runtime tests to determine what  they will use, but I believe this is mostly with assembler code rather than a higher-level language compiled differently.
jcaron
CC BY-SA 4.0
2024-09-12T09:05:14.333Z
It seems a bit late in the game to worry about 32-bit platforms. My current machine is 10 years old, 64-bit, and wasn't exactly bleeding edge when I got it, either.
Karl Knechtel
<p>On a 32-bit platform 64-bit integers will be more than twice as expensive as 32-bit ones.</p>
<p>First there are the operations to consider.</p>
<ul>
<li>Simple addition and subtraction will require two 32-bit operation</li>
<li>Multiplication will require at best, a &quot;multiply long&quot; operation and two &quot;multiply accumulate&quot; operations. If the architecture doesn't have multiply long and multiply accumulate then things get more complex.</li>
<li>Division is likely to result in calling a library routine.</li>
</ul>
<p>Then there is the issue of register pressure. A 64-bit value on a 32-bit system takes up two registers. So you have essentially cut your usable registers in half. That means more spills, and (on architectures that pass parameters in registers) more chance of running past the limit for arguments in registers and having to pass them on the stack.</p>
<hr />
<p>An alternative would be to use SIMD units, however there are some difficulties with doing so (the list below is focused on x86 and arm as those are the architectures I'm most familiar with but I expect similar issues to show up on other architectures).</p>
<ol>
<li>The design of MMX was horribly busted, it would leave the FPU in an invalid state requiring it to be reset before doing any floating point operations. SSE2 fixed that problem, but SSE2 only appeared much later.</li>
<li>Baseline targets often either don't have SIMD instructions at all or only have a very limited choice of them.</li>
<li>The set of availble operations is often quite limited. SSE2 has addition and bitwise operations, but not subtraction, multiplication or division.</li>
<li>SIMD instructions work with their own registers. This is a mixed blessing, on the one hand it reduces pressure on the main integer registers. On the other hand it often entails extra operations to move values in to and out of the SIMD registers.</li>
</ol>
<p>I don't think moving individual 64-bit integer operations to the SIMD unit is something I have ever seen a compiler do. Presumably because the aforementioned difficulties make it not worthwhile.</p>

CC BY-SA 4.0
2023-09-27T18:22:39.627Z
2023-09-29T15:23:49.210Z
2023-09-29T15:23:49.210Z
Peter Green
CC BY-SA 4.0
2023-09-28T00:59:44.227Z
I don't think this is always true. Consider MMX and SSE on x86.
user71659
# What, if any, runtime cost is incurred by using 64-bit ints on 32-bit platforms in LLVM?
Posted by: username_0 on 2023-09-27
I'm writing a language frontend for LLVM, and I noticed that the IR docs say that integers of (almost) any width can be used without limit. I presume this to mean that LLVM or its backends convert numbers with a width larger than the target's width into multiple chunks during execution. I also see that the docs make no mention of not using 64-bit ints on 32-bit platforms, since the backends presumably split 64-bit ints in half in that case. However, this splitting might incur a runtime cost of some sort. So, how big is the performance cost (if any; maybe LLVM can optimize this away in some situations) of making my frontend emit 64-bit integers regardless of the width of the target platform, as opposed to having it only emit 32-bit ones on 32-bit platforms and only emit 64-bit ones on 64-bit platforms? (The performance cost will of course vary by context; I'm asking if it is consistently large enough to warrant making the compiler check for it.)
**Tags:** compilers integers llvm
> **Comments:**
> **username_1**: I think this question needs some clarification. Runtime cost in contrast to what? Lower bitcounts in the same architecture or 64 bits in the 64 bit equivalent platform? This compiler explorer example https://godbolt.org/z/rE1YzE948 seems to imply it depends on use case as well, since adding is just one more instruction, yet 64bit multiplication more than doubles the instruction count of 32bit multiplication.  
> **username_2**: Note that word size may not be the same for everything on some architectures. Some processors have supported (some) 64-bit integer operations while still only supporting 32-bit addressing for instance.  
> **username_0**: @jcaron Huh, I didn't know that. Interesting! I wonder if backends for those processors take advantage of that fact.  
> **username_2**: @Ginger one issue in some cases is that such features may vary from one processor to the next in the same architecture, so either you have to target a sub-family of processors, or the decision must be made at runtime, which is a lot more likely in libraries than in the generic code generated by the compiler. Some processing-heavy libraries (e.g. crypto) will have lots of runtime tests to determine what  they will use, but I believe this is mostly with assembler code rather than a higher-level language compiled differently.  
> **username_3**: It seems a bit late in the game to worry about 32-bit platforms. My current machine is 10 years old, 64-bit, and wasn't exactly bleeding edge when I got it, either.  
---
## 1 answers
### Answer by username_4 on 2023-09-27. Score: 12
On a 32-bit platform 64-bit integers will be more than twice as expensive as 32-bit ones.

First there are the operations to consider.

* Simple addition and subtraction will require two 32-bit operation
* Multiplication will require at best, a "multiply long" operation and two "multiply accumulate" operations. If the architecture doesn't have multiply long and multiply accumulate then things get more complex.
* Division is likely to result in calling a library routine.

Then there is the issue of register pressure. A 64-bit value on a 32-bit system takes up two registers. So you have essentially cut your usable registers in half. That means more spills, and (on architectures that pass parameters in registers) more chance of running past the limit for arguments in registers and having to pass them on the stack.

---

An alternative would be to use SIMD units, however there are some difficulties with doing so (the list below is focused on x86 and arm as those are the architectures I'm most familiar with but I expect similar issues to show up on other architectures).

1. The design of MMX was horribly busted, it would leave the FPU in an invalid state requiring it to be reset before doing any floating point operations. SSE2 fixed that problem, but SSE2 only appeared much later.
2. Baseline targets often either don't have SIMD instructions at all or only have a very limited choice of them.
3. The set of availble operations is often quite limited. SSE2 has addition and bitwise operations, but not subtraction, multiplication or division.
4. SIMD instructions work with their own registers. This is a mixed blessing, on the one hand it reduces pressure on the main integer registers. On the other hand it often entails extra operations to move values in to and out of the SIMD registers.

I don't think moving individual 64-bit integer operations to the SIMD unit is something I have ever seen a compiler do. Presumably because the aforementioned difficulties make it not worthwhile.
> **Comments:**
> **username_5** (2023-09-28): I don't think this is always true. Consider MMX and SSE on x86.  
---
