This is an archive of the discontinued LLVM Phabricator instance.

[GlobalISel] Widen one type at the time for insert/extract vector elt
Needs ReviewPublic

Authored by Petar.Avramovic on Oct 28 2019, 8:20 AM.

Details

Summary

In widenScalar for G_INSERT_VECTOR_ELT and G_EXTRACT_VECTOR_ELT, widen
scalar of TypeIdx that corresponds to scalar element that is being
inserted/extracted used to also affect vector type at another TypeIdx.
It used to widen vector scalar type and keep same number of elements.
Change widenScalar for these opcodes to only affect operands with LLT
that corresponds to same TypeIdx.
This allows to widen only scalar type and leave vector type unchanged.
Old functionality of elt widenScalar can be achieved by two widenScalar
calls for elt(minScalar) and vector(minScalarOrElt) TypeIdx with same
scalar type. Update AMDGPULegalizerInfo.

Diff Detail

Event Timeline

Herald added a project: Restricted Project. · View Herald TranscriptOct 28 2019, 8:20 AM
Petar.Avramovic marked an inline comment as done.Oct 28 2019, 8:25 AM
Petar.Avramovic added inline comments.
llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
1784

G_INSERT_VECTOR_ELT uses G_ANYEXT for its vector TypeIdx (0). Should this one also use G_ANYEXT?

arsenm added a comment.Nov 1 2019, 9:54 AM

I don't understand the motivation. The vector element and insert element type need to match, but it appears there's a missing verifier check

llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
1784

This should probably be changed in a separate patch

I don't understand the motivation.
The vector element and insert element type need to match, but it appears there's a missing verifier check

This is definitely true for llvm-ir insertelement and extractvalue.
But SDAG nodes ISD::INSERT_VECTOR_ELT and ISD::EXTRACT_VECTOR_ELT don't follow this,
Mips uses DAGTypeLegalizer::PromoteIntegerResult for i8 and i16 and promotes them to i32 leaving vector scalar type unchanged.
In .td file element being inserted/extracted has i32 operand type (for i8, i16 and i32) and instruction is selected based on vector type (v16i8, v8i16, v4i32).

I have just saw these two asserts that forbid different types of vector scalar and element scalar
https://github.com/llvm/llvm-project/blob/a0324e911374441151903ed0d828e0fc1994c167/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp#L1090
https://github.com/llvm/llvm-project/blob/a0324e911374441151903ed0d828e0fc1994c167/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp#L1100
Widen scalar change does not trigger asserts since it only changes operand instead of making new instruction. How do we approach this issue then?
Btw, based on G_ZEXTLOAD and G_SEXTLOAD, are G_SEXT_EXTRACT_VECTOR_ELT and G_ZEXT_EXTRACT_VECTOR_ELT a consideration?
They would have different element scalar then vector scalar.

I have just saw these two asserts that forbid different types of vector scalar and element scalar
https://github.com/llvm/llvm-project/blob/a0324e911374441151903ed0d828e0fc1994c167/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp#L1090
https://github.com/llvm/llvm-project/blob/a0324e911374441151903ed0d828e0fc1994c167/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp#L1100
Widen scalar change does not trigger asserts since it only changes operand instead of making new instruction. How do we approach this issue then?
Btw, based on G_ZEXTLOAD and G_SEXTLOAD, are G_SEXT_EXTRACT_VECTOR_ELT and G_ZEXT_EXTRACT_VECTOR_ELT a consideration?
They would have different element scalar then vector scalar.

Based on the fact that we have separate G_BUILD_VECTOR and G_BUILD_VECTOR_TRUNC, I think there should be a separate opcode for vector operations which implicitly convert

I don't fully understand G_BUILD_VECTOR_TRUNC. Such opcode does not exist in llvm-ir and as such can only be created in legalizer or later (at the moment at least). The problem here is the context sensitive legality (we still avoid this) along side with type legality. e.g. types might be fine but we still can't select an instructions because vector is built from different virtual registers (so splat is not an option) and we should perform lower. At the current state of legalizer I don't think it is possible to have it legal for type and as such I planned to handle it with custom legalization by either context sensitive select or lower.

Reasoning similarly to G_BUILD_VECTOR_TRUNC it is probably good thing to have verbose corner case opcodes for vector operations which implicitly convert.
If I understood correctly, we need 4 new generic opcodes: G_INSERT_VECTOR_ELT_TRUNC
G_SEXT_EXTRACT_VECTOR_ELT
G_ZEXT_EXTRACT_VECTOR_ELT
G_ANYEXT_EXTRACT_VECTOR_ELT.
For MIPS, I would create them in preLegalizerCombiner.

Only difference between G_INSERT_VECTOR_ELT_TRUNC, G_ANYEXT_EXTRACT_VECTOR_ELT and G_INSERT_VECTOR_ELT, G_EXTRACT_VECTOR_ELT I see is widen scalar for scalar type.
Do scalar and vector scalar type have to be always different for them,
i.e. is %Dest:_(<2 x s8>) = G_INSERT_VECTOR_ELT_TRUNC %Src:_(<2 x s8>), %Elt:_(s8), %Index:_(s32) allowed or it must be G_INSERT_VECTOR_ELT instead.
If later, how do we widen scalar for G_INSERT_VECTOR_ELT (it should change opcode to G_INSERT_VECTOR_ELT_TRUNC). Something like WidenEltScalar that would be used only for G_INSERT_VECTOR_ELT and G_EXTRACT_VECTOR_ELT?