LLVM IR i128

Hi everyone!
Here, I have a question and am curious about i128. I want to know how the LLVM handle i128, because many compiler backend doesn’t support i128 directly. So I am very curious and want to how the llvm handle this situation? Besides i128, such as i256, i512, even i24? Thanks.

Best Regards

Wu Zhao

Big data types corresponds to its equivalent vector types, for example, 16 x i8, 8 x i16, 4 x i32 etc.

Cheers,

Erkan.

I asked a similar question last year here. Operations on types iN with no direct translation into one assembly instruction seem to be translated into several ones correctly.

For 64-bit X86 code we have had good success with using up-to 128-bit
integers (this includes say 36-bit or even 2-bit integers).

I asked a similar question last year here. Operations on types iN with no
direct translation into one assembly instruction seem to be translated into
several ones correctly.

In my experience this is *definitely* not true in practise, at least
on x86. Using larger than 128-bit integers we have hit assertion
failures, crashes and miscompiles. Things are even worse for vectors
of non-legal(?) types (say <2 x i2>).

Some of the issue that we hit after giving up on vectorized code and
relying directly on LLVM for wider-than-legal types:

http://llvm.org/bugs/show_bug.cgi?id=20011 (crash with <2 x i2>)
http://llvm.org/bugs/show_bug.cgi?id=20012 (error when storing <2 x i4>)
http://llvm.org/bugs/show_bug.cgi?id=19797 (assert failure on
multiplication of i192)
http://llvm.org/bugs/show_bug.cgi?id=20921 (assert failure on stores
and loads of i193)
http://llvm.org/bugs/show_bug.cgi?id=21184 (miscompilation of
wider-than-legal types)

I would *really* wish that the documentation made sure to mention,
that wider-than-legal types are not expected to work.

- Jaak

OK. Thanks very much. By the way, does anybody know which part of the llvm source code (or clang source code) handle this situation? Because I want to dig deeper and know how to handle this more detail.

Best Regards

Wu Zhao

Wider-than-legal types are not necessarily handled as vectors.

On x86, something like i128 is handled, within limitations, using multiple non-vector instructions. e.g. adding i128 lowers to ADD followed by ADC.

Things I’ve noticed:

  • The x86 lowering does not generate loops even in cases where they might be reasonable. If you add two i2048 values, then you’ll get 32 64-bit adds, unrolled.

  • Some ops are not supported, e.g. multiplying two i128 will result in a crash. However, i128 x i128 seems to work.

In general, you can probably rely on the DAG legalization to generate correct code for values twice as wide as your processor can reasonably handle (e.g. i128 for x64_64) and you’re best to steer clear of anything larger. Use GMP or roll your own for those cases.

Perhaps this will be useful to start looking inside LLVM:

SelectionDAG LegalizeTypes Phase The Legalize phase is in charge of converting a DAG to only use the types that are natively supported by the target. Sameer.