6
$\begingroup$

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.)

$\endgroup$
4
  • 1
    $\begingroup$ 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 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. $\endgroup$
    – kouta-kun
    Commented Sep 27, 2023 at 15:39
  • 1
    $\begingroup$ 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. $\endgroup$
    – jcaron
    Commented Sep 28, 2023 at 0:47
  • $\begingroup$ @jcaron Huh, I didn't know that. Interesting! I wonder if backends for those processors take advantage of that fact. $\endgroup$
    – Ginger
    Commented Sep 28, 2023 at 11:27
  • $\begingroup$ @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. $\endgroup$
    – jcaron
    Commented Sep 28, 2023 at 11:38

1 Answer 1

9
$\begingroup$

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.

$\endgroup$
2
  • 2
    $\begingroup$ I don't think this is always true. Consider MMX and SSE on x86. $\endgroup$
    – user71659
    Commented Sep 28, 2023 at 0:59
  • 1
    $\begingroup$ @user71659 64-bit integer arithmetic in MMX and SSE is severely lacking. It won't cost double the number of registers at least, but MMX didn't even have 64-bit subtraction or comparison, that's how bare-bones it was. A proper 64-bit multiplication in a SIMD register didn't come until AVX512 $\endgroup$
    – user1030
    Commented Sep 28, 2023 at 6:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .