vector type legalization

Hi,

I am trying to understand how vector type legalization works. In particular, I'm looking at i8 vector types on x86 (with sse42 features)

v3i8 gets widened to v4i8 and then operations get unrolled (scalarized) because v4i8 is not a legal type whereas v4i8 gets promoted to v4i32. Why doesn't v3i8 (or even v4i8) get widened to v16i8? Alternatively, v3i8 could be widened to v4i8 then promoted to v4i32 but this doesn't happen either.

Can anyone provide some insight into why vector type legalization works the way it does?

Thanks,
paul

Hi Paul,

You can read about it here: http://blog.llvm.org/2011/12/llvm-31-vector-changes.html

Hi,

I am trying to understand how vector type legalization works. In particular, I'm looking at i8 vector types on x86 (with sse42 features)

v3i8 gets widened to v4i8 and then operations get unrolled (scalarized) because v4i8 is not a legal type whereas v4i8 gets

This does not sound right. v3i8 -> v4i8 is okay. But the next step should be v4i8 -> v4i32. The operation nay be scalarized in the vector legalization phase.

Hi Nadav,

Hi Paul,

You can read about it here:
http://blog.llvm.org/2011/12/llvm-31-vector-changes.html

Hi,

I am trying to understand how vector type legalization works. In
particular, I'm looking at i8 vector types on x86 (with sse42 features)

v3i8 gets widened to v4i8 and then operations get unrolled (scalarized)
because v4i8 is not a legal type whereas v4i8 gets

This does not sound right. v3i8 -> v4i8 is okay. But the next step
should be v4i8 -> v4i32. The operation nay be scalarized in the vector
legalization phase.

What I'm looking at is a v3i8 add. In DAGTypeLegalizer::WidenVecRes_Binary
the operation gets scalarized (DAG.UnrollVector). The input N is
"0x51c1d60: v3i8 = add 0x51c1860, 0x51c1c60 [ORD=5] [ID=0]" and the
WidenVT is v4i8. The code ends up in the NumElts == 1 path which causes
scalarization.

The debug dump shows "Widen node result 0: 0x563dd20: v3i8 = add
0x563d820, 0x563dc20 [ORD=5] [ID=0]". To me it doesn't look like it's
possible to both widen and promote an operation..

Paul

This is a bug in the implementation of WidenVecRes_Binary. On line 1546 it assumes that “Widen” is the last phase of type-legalization and we check if the result is a legal type. But actually we want to continue and promote the elements of the vector. In other cases we may want to widen (to the next power of two) and later split in half because the vector is too big.

Hi Nadav,

I am not sure :slight_smile:

Thanks for the tip. I modified WidenVecRes_Binary match WidenVecRes_{Unary/Ternary} and it does the promotion and generates much better code. Why is WidenVecRes_Binary so much more complicated than the Unary/Binary functions? None of the operations in the cases for WidenVecRes_Binary seem any more special then the operations that use WidenVecRes_Unary..

I am not sure :slight_smile:

The reason is special handling for DIV and REM which can trap. The TargetLowering function canOpTrap is only used in WidenVecRes_Binary and the default behaviour returns true for the DIV and REM ops (no target seems to overload this behaviour). The Unary and Ternary functions just assume those operations don't trap.

An easy fix is to simply split WidenVecRes_Binary into two functions—one that keeps the behaviour of handling ops that trap and one that assumes no traps. I'll prepare a patch.

paul