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.
Details
Diff Detail
Event Timeline
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? |
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.
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?
G_INSERT_VECTOR_ELT uses G_ANYEXT for its vector TypeIdx (0). Should this one also use G_ANYEXT?