larger-than-legal types in LLVM IR

Are there any LLVM guidelines / documentation for handling larger-than-legal data types (either scalars or vectors)?

Currently, the backend may crash [1], miscompile [2], or make a big mess [3] when presented with data types that are bigger than native.

In the case of [3], is it a bug in the vectorizer to produce a non-legal vector type (<16 x i64>) or should the backend be able to handle that more reasonably? In that particular case, things are further complicated because -loop-unroll is able to completely remove the loop and the large vector type disappears.

[1] http://llvm.org/bugs/show_bug.cgi?id=19797
[2] http://llvm.org/bugs/show_bug.cgi?id=21184
[3] http://llvm.org/bugs/show_bug.cgi?id=20225

Hi Sanjay,

Are there any LLVM guidelines / documentation for handling larger-than-legal data types (either scalars or vectors)?

Currently, the backend may crash [1], miscompile [2], or make a big mess [3] when presented with data types that are bigger than native.

In the case of [3], is it a bug in the vectorizer to produce a non-legal vector type (<16 x i64>) or should the backend be able to handle that more reasonably? In that particular case, things are further complicated because -loop-unroll is able to completely remove the loop and the large vector type disappears.

I’d say it is legal for the vectorizer to produce non-legal types as long as the expected codegen cost is smaller than the scalar version. That being said, this is possible there is a bug in the vectorizer cost model or the use of this cost model!

Cheers,
-Quentin

Are there any LLVM guidelines / documentation for handling larger-than-legal
data types (either scalars or vectors)?

Currently, the backend may crash [1], miscompile [2], or make a big mess [3]
when presented with data types that are bigger than native.

I think scalars and vectors shouldn't be lumped together here.

IMHO, the only rule should be "it's all legal".

In practice, larger-than-legal vectors shouldn't pose a problem.
(much) Larger-than-legal integers however, aren't well supported. As
Duncan says in [1], it's just that no one implemented the arbitrary
precision legalization.
But you're right, if saying we support any size is a lie, maybe we
should reconsider. I'll leave that part to others though.

In the case of [3], is it a bug in the vectorizer to produce a non-legal
vector type (<16 x i64>) or should the backend be able to handle that more
reasonably? In that particular case, things are further complicated because
-loop-unroll is able to completely remove the loop and the large vector type
disappears.

Like Quentin says, this looks like a bug in the cost model.

From what I've seen, the loop vectorizer cost model looks at

load/store/PHI when selecting the vectorization factor (cf.
getWidestType).
Later, when computing the cost for each possible factor,
BasicTTI::getCmpSelInstrCost decides that an icmp <16 x i64> costs 8,
because it only counts the number of splits.

I'm not clear about the solution in this case. I'm guessing
getWidestType ignores other instructions justifiably on purpose.
Maybe the legalization cost scaling in BasicTTI should be superlinear?
i.e., (cost of 4 splits) > 2 * (cost of 2 splits)

As a quick experiment, changing getCmpSelInstrCost to square the
TypeLegalizationCost produces a better-looking <4 x i64>.

-Ahmed

Are there any LLVM guidelines / documentation for handling larger-than-legal data types (either scalars or vectors)?

Currently, the backend may crash [1], miscompile [2], or make a big mess [3] when presented with data types that are bigger than native.

In the case of [3], is it a bug in the vectorizer to produce a non-legal vector type (<16 x i64>) or should the backend be able to handle that more reasonably? In that particular case, things are further complicated because -loop-unroll is able to completely remove the loop and the large vector type disappears.

Crashing on an illegal type is a bug.

We can sometimes get bigger than legal types if the loop has code that goes from type to the (e.g casts).

What should happen is that codegen handles those types gracefully and that the cost model estimated the cost of the generated code correctly (conservatively).

If the cost does not match the genarated code we should fix the cost model: either by returning a target specific cost eg. X86TTI or by adjusting the shared cost model basictti.