-
Notifications
You must be signed in to change notification settings - Fork 100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for vector types #284
Comments
Should new operations be created for vector types? Or should the existing ops be reused? I am guessing new ops are needed, since the semantics for some operations, especially the relational operators, are quite different for vectors than for scalars. |
This is a very relevant question!
Right, similar to the
|
https://clang.llvm.org/docs/LanguageExtensions.html#vectors-and-extended-vectors has some useful information about Clang's support for vector types. There are five different kinds of vector types: GCC, OpenCL, Arm NEON, Arm SVE, and AltiVec. I believe that all except for SVE can share the same ClangIR vector type with an element type and a size. The Arm SVE vector types are different and will need their own ClcangIR type because they don't have a compile-time size. |
Sounds good, looks like both SVE & RISC-V V have that property. Perhaps when we get there we should generalize the vector types to use |
I am rethinking having separate CIR types for fixed-sized vectors and scalable vectors. Base MLIR has one meta-type for both (which also covers multidimensional arrays). But I'll figure that out later. Right now I'm implementing fixed-sized vector types. Once that is mostly working I'll decide what to do about scalable types. |
This is the first part of implementing vector types and vector operations in ClangIR, issue #284. This is enough to compile this test program. I haven't tried to do anything beyond that yet. ``` typedef int int4 __attribute__((vector_size(16))); int main(int argc, char** argv) { int4 a = { 1, argc, argc + 1, 4 }; int4 b = { 5, argc + 2, argc + 3, 8 }; int4 c = a + b; return c[1]; } ``` This change includes: * Fixed-sized vector types which are parameterized on the element type and the number of elements. For example, `!cir.vector<s32i x 4>`. (No scalable vector types yet; those will come later.) * New operation `cir.vec` which creates an object of a vector type with the given operands. * New operation `cir.vec_elem` which extracts an element from a vector. (The array subscript operation doesn't work here because the result is an rvalue, not an lvalue.) * Basic binary arithmetic operations on vector types, though only addition has been tested. There are no unary operators, comparison operators, casts, or shuffle operations yet. Those will all come later.
This is the first part of implementing vector types and vector operations in ClangIR, issue #284. This is enough to compile this test program. I haven't tried to do anything beyond that yet. ``` typedef int int4 __attribute__((vector_size(16))); int main(int argc, char** argv) { int4 a = { 1, argc, argc + 1, 4 }; int4 b = { 5, argc + 2, argc + 3, 8 }; int4 c = a + b; return c[1]; } ``` This change includes: * Fixed-sized vector types which are parameterized on the element type and the number of elements. For example, `!cir.vector<s32i x 4>`. (No scalable vector types yet; those will come later.) * New operation `cir.vec` which creates an object of a vector type with the given operands. * New operation `cir.vec_elem` which extracts an element from a vector. (The array subscript operation doesn't work here because the result is an rvalue, not an lvalue.) * Basic binary arithmetic operations on vector types, though only addition has been tested. There are no unary operators, comparison operators, casts, or shuffle operations yet. Those will all come later.
This is part 2 of implementing vector types and vector operations in ClangIR, issue llvm#284. Create new operation `cir.vec.insert`, which changes one element of an existing vector object and returns the modified vector object. The input and output vectors are prvalues; this operation does not touch memory. The assembly format and the order of the arguments match that of llvm.insertelement in the LLVM dialect, since the operations have identical semantics. Implement vector element lvalues in class `LValue`, adding member functions `getVectorAddress()`, `getVectorPointer()`, `getVectorIdx()`, and `MakeVectorElt(...)`. The assembly format for operation `cir.vec.extract` was changed to match that of llvm.extractelement in the LLVM dialect, since the operations have identical semantics. These two features, `cir.vec.insert` and vector element lvalues, are used to implement `v[n] = e`, where `v` is a vector. This is a little tricky, because `v[n]` isn't really an lvalue, as its address cannot be taken. The only place it can be used as an lvalue is on the left-hand side of an assignment. Implement unary operators on vector objects (except for logical not on a vector mask, which will be covered in a future commit for boolean vectors). The code for lowering cir.unary for all types, in `CIRUnaryOpLowering::matchAndRewrite`, was largely rewritten. Support for unary `+` on non-vector pointer types was added. (It was already supported and tested in AST->ClangIR CodeGen, but was missing from ClangIR->LLVM Dialect lowering.) Add tests for all binary vector arithmetic operations other than relational operators and shift operators. There were all working after the previous vector types commit, but only addition had beet tested at the time.
This is part 2 of implementing vector types and vector operations in ClangIR, issue #284. Create new operation `cir.vec.insert`, which changes one element of an existing vector object and returns the modified vector object. The input and output vectors are prvalues; this operation does not touch memory. The assembly format and the order of the arguments match that of llvm.insertelement in the LLVM dialect, since the operations have identical semantics. Implement vector element lvalues in class `LValue`, adding member functions `getVectorAddress()`, `getVectorPointer()`, `getVectorIdx()`, and `MakeVectorElt(...)`. The assembly format for operation `cir.vec.extract` was changed to match that of llvm.extractelement in the LLVM dialect, since the operations have identical semantics. These two features, `cir.vec.insert` and vector element lvalues, are used to implement `v[n] = e`, where `v` is a vector. This is a little tricky, because `v[n]` isn't really an lvalue, as its address cannot be taken. The only place it can be used as an lvalue is on the left-hand side of an assignment. Implement unary operators on vector objects (except for logical not on a vector mask, which will be covered in a future commit for boolean vectors). The code for lowering cir.unary for all types, in `CIRUnaryOpLowering::matchAndRewrite`, was largely rewritten. Support for unary `+` on non-vector pointer types was added. (It was already supported and tested in AST->ClangIR CodeGen, but was missing from ClangIR->LLVM Dialect lowering.) Add tests for all binary vector arithmetic operations other than relational operators and shift operators. There were all working after the previous vector types commit, but only addition had beet tested at the time. Co-authored-by: Bruno Cardoso Lopes <bcardosolopes@users.noreply.github.com>
This is part 3 of implementing vector types and vector operations in ClangIR, issue llvm#284. Create new operation `cir.vec.cmp` which implements the relational comparison operators (`== != < > <= >=`) on vector types. A new operation was created rather than reusing `cir.cmp` because the result is a vector of a signed intergral type, not a `bool`. Add CodeGen and Lowering tests for vector comparisons. Fix the floating-point comparison predicate when lowering to LLVM. To handle NaN values correctly, the comparisons need to be ordered rather than unordered. (Except for `!=`, which needs to be unordered.) For example, "ueq" was changed to "oeq".
This is the first part of implementing vector types and vector operations in ClangIR, issue #284. This is enough to compile this test program. I haven't tried to do anything beyond that yet. ``` typedef int int4 __attribute__((vector_size(16))); int main(int argc, char** argv) { int4 a = { 1, argc, argc + 1, 4 }; int4 b = { 5, argc + 2, argc + 3, 8 }; int4 c = a + b; return c[1]; } ``` This change includes: * Fixed-sized vector types which are parameterized on the element type and the number of elements. For example, `!cir.vector<s32i x 4>`. (No scalable vector types yet; those will come later.) * New operation `cir.vec` which creates an object of a vector type with the given operands. * New operation `cir.vec_elem` which extracts an element from a vector. (The array subscript operation doesn't work here because the result is an rvalue, not an lvalue.) * Basic binary arithmetic operations on vector types, though only addition has been tested. There are no unary operators, comparison operators, casts, or shuffle operations yet. Those will all come later.
This is part 2 of implementing vector types and vector operations in ClangIR, issue #284. Create new operation `cir.vec.insert`, which changes one element of an existing vector object and returns the modified vector object. The input and output vectors are prvalues; this operation does not touch memory. The assembly format and the order of the arguments match that of llvm.insertelement in the LLVM dialect, since the operations have identical semantics. Implement vector element lvalues in class `LValue`, adding member functions `getVectorAddress()`, `getVectorPointer()`, `getVectorIdx()`, and `MakeVectorElt(...)`. The assembly format for operation `cir.vec.extract` was changed to match that of llvm.extractelement in the LLVM dialect, since the operations have identical semantics. These two features, `cir.vec.insert` and vector element lvalues, are used to implement `v[n] = e`, where `v` is a vector. This is a little tricky, because `v[n]` isn't really an lvalue, as its address cannot be taken. The only place it can be used as an lvalue is on the left-hand side of an assignment. Implement unary operators on vector objects (except for logical not on a vector mask, which will be covered in a future commit for boolean vectors). The code for lowering cir.unary for all types, in `CIRUnaryOpLowering::matchAndRewrite`, was largely rewritten. Support for unary `+` on non-vector pointer types was added. (It was already supported and tested in AST->ClangIR CodeGen, but was missing from ClangIR->LLVM Dialect lowering.) Add tests for all binary vector arithmetic operations other than relational operators and shift operators. There were all working after the previous vector types commit, but only addition had beet tested at the time. Co-authored-by: Bruno Cardoso Lopes <bcardosolopes@users.noreply.github.com>
This is part 3 of implementing vector types and vector operations in ClangIR, issue llvm#284. Create new operation `cir.vec.cmp` which implements the relational comparison operators (`== != < > <= >=`) on vector types. A new operation was created rather than reusing `cir.cmp` because the result is a vector of a signed intergral type, not a `bool`. Add CodeGen and Lowering tests for vector comparisons. Fix the floating-point comparison predicate when lowering to LLVM. To handle NaN values correctly, the comparisons need to be ordered rather than unordered. (Except for `!=`, which needs to be unordered.) For example, "ueq" was changed to "oeq".
This is part 3 of implementing vector types and vector operations in ClangIR, issue #284. Create new operation `cir.vec.cmp` which implements the relational comparison operators (`== != < > <= >=`) on vector types. A new operation was created rather than reusing `cir.cmp` because the result is a vector of a signed intergral type, not a `bool`. Add CodeGen and Lowering tests for vector comparisons. Fix the floating-point comparison predicate when lowering to LLVM. To handle NaN values correctly, the comparisons need to be ordered rather than unordered. (Except for `!=`, which needs to be unordered.) For example, "ueq" was changed to "oeq".
This is part 4 of implementing vector types and vector operations in ClangIR, issue llvm#284. This change has three small additions. Implement a "vector splat" conversion, which converts a scalar into vector, initializing all the elements of the vector with the scalar. Implement incomplete initialization of a vector, where the number of explicit initializers is less than the number of elements in the vector. The rest of the elements are implicitly zero initialized. Implement conversions between different vector types. The language rules require that the two types be the same size (in bytes, not necessarily in the number of elements). These conversions are always implemented with a bitcast. The first two changes only required changes to the AST -> ClangIR code gen. There are no changes to the ClangIR dialect, so no changes to the LLVM lowering were needed. The third part only required a change to a validation rule. The code to implement a vector bitcast was already present. The compiler just needed to stop rejecting it as invalid ClangIR.
This is part 4 of implementing vector types and vector operations in ClangIR, issue #284. This change has three small additions. Implement a "vector splat" conversion, which converts a scalar into vector, initializing all the elements of the vector with the scalar. Implement incomplete initialization of a vector, where the number of explicit initializers is less than the number of elements in the vector. The rest of the elements are implicitly zero initialized. Implement conversions between different vector types. The language rules require that the two types be the same size (in bytes, not necessarily in the number of elements). These conversions are always implemented with a bitcast. The first two changes only required changes to the AST -> ClangIR code gen. There are no changes to the ClangIR dialect, so no changes to the LLVM lowering were needed. The third part only required a change to a validation rule. The code to implement a vector bitcast was already present. The compiler just needed to stop rejecting it as invalid ClangIR.
This is the first part of implementing vector types and vector operations in ClangIR, issue #284. This is enough to compile this test program. I haven't tried to do anything beyond that yet. ``` typedef int int4 __attribute__((vector_size(16))); int main(int argc, char** argv) { int4 a = { 1, argc, argc + 1, 4 }; int4 b = { 5, argc + 2, argc + 3, 8 }; int4 c = a + b; return c[1]; } ``` This change includes: * Fixed-sized vector types which are parameterized on the element type and the number of elements. For example, `!cir.vector<s32i x 4>`. (No scalable vector types yet; those will come later.) * New operation `cir.vec` which creates an object of a vector type with the given operands. * New operation `cir.vec_elem` which extracts an element from a vector. (The array subscript operation doesn't work here because the result is an rvalue, not an lvalue.) * Basic binary arithmetic operations on vector types, though only addition has been tested. There are no unary operators, comparison operators, casts, or shuffle operations yet. Those will all come later.
This is part 2 of implementing vector types and vector operations in ClangIR, issue #284. Create new operation `cir.vec.insert`, which changes one element of an existing vector object and returns the modified vector object. The input and output vectors are prvalues; this operation does not touch memory. The assembly format and the order of the arguments match that of llvm.insertelement in the LLVM dialect, since the operations have identical semantics. Implement vector element lvalues in class `LValue`, adding member functions `getVectorAddress()`, `getVectorPointer()`, `getVectorIdx()`, and `MakeVectorElt(...)`. The assembly format for operation `cir.vec.extract` was changed to match that of llvm.extractelement in the LLVM dialect, since the operations have identical semantics. These two features, `cir.vec.insert` and vector element lvalues, are used to implement `v[n] = e`, where `v` is a vector. This is a little tricky, because `v[n]` isn't really an lvalue, as its address cannot be taken. The only place it can be used as an lvalue is on the left-hand side of an assignment. Implement unary operators on vector objects (except for logical not on a vector mask, which will be covered in a future commit for boolean vectors). The code for lowering cir.unary for all types, in `CIRUnaryOpLowering::matchAndRewrite`, was largely rewritten. Support for unary `+` on non-vector pointer types was added. (It was already supported and tested in AST->ClangIR CodeGen, but was missing from ClangIR->LLVM Dialect lowering.) Add tests for all binary vector arithmetic operations other than relational operators and shift operators. There were all working after the previous vector types commit, but only addition had beet tested at the time. Co-authored-by: Bruno Cardoso Lopes <bcardosolopes@users.noreply.github.com>
This is part 3 of implementing vector types and vector operations in ClangIR, issue #284. Create new operation `cir.vec.cmp` which implements the relational comparison operators (`== != < > <= >=`) on vector types. A new operation was created rather than reusing `cir.cmp` because the result is a vector of a signed intergral type, not a `bool`. Add CodeGen and Lowering tests for vector comparisons. Fix the floating-point comparison predicate when lowering to LLVM. To handle NaN values correctly, the comparisons need to be ordered rather than unordered. (Except for `!=`, which needs to be unordered.) For example, "ueq" was changed to "oeq".
This is part 4 of implementing vector types and vector operations in ClangIR, issue #284. This change has three small additions. Implement a "vector splat" conversion, which converts a scalar into vector, initializing all the elements of the vector with the scalar. Implement incomplete initialization of a vector, where the number of explicit initializers is less than the number of elements in the vector. The rest of the elements are implicitly zero initialized. Implement conversions between different vector types. The language rules require that the two types be the same size (in bytes, not necessarily in the number of elements). These conversions are always implemented with a bitcast. The first two changes only required changes to the AST -> ClangIR code gen. There are no changes to the ClangIR dialect, so no changes to the LLVM lowering were needed. The third part only required a change to a validation rule. The code to implement a vector bitcast was already present. The compiler just needed to stop rejecting it as invalid ClangIR.
This is the first part of implementing vector types and vector operations in ClangIR, issue llvm#284. This is enough to compile this test program. I haven't tried to do anything beyond that yet. ``` typedef int int4 __attribute__((vector_size(16))); int main(int argc, char** argv) { int4 a = { 1, argc, argc + 1, 4 }; int4 b = { 5, argc + 2, argc + 3, 8 }; int4 c = a + b; return c[1]; } ``` This change includes: * Fixed-sized vector types which are parameterized on the element type and the number of elements. For example, `!cir.vector<s32i x 4>`. (No scalable vector types yet; those will come later.) * New operation `cir.vec` which creates an object of a vector type with the given operands. * New operation `cir.vec_elem` which extracts an element from a vector. (The array subscript operation doesn't work here because the result is an rvalue, not an lvalue.) * Basic binary arithmetic operations on vector types, though only addition has been tested. There are no unary operators, comparison operators, casts, or shuffle operations yet. Those will all come later.
This is part 2 of implementing vector types and vector operations in ClangIR, issue llvm#284. Create new operation `cir.vec.insert`, which changes one element of an existing vector object and returns the modified vector object. The input and output vectors are prvalues; this operation does not touch memory. The assembly format and the order of the arguments match that of llvm.insertelement in the LLVM dialect, since the operations have identical semantics. Implement vector element lvalues in class `LValue`, adding member functions `getVectorAddress()`, `getVectorPointer()`, `getVectorIdx()`, and `MakeVectorElt(...)`. The assembly format for operation `cir.vec.extract` was changed to match that of llvm.extractelement in the LLVM dialect, since the operations have identical semantics. These two features, `cir.vec.insert` and vector element lvalues, are used to implement `v[n] = e`, where `v` is a vector. This is a little tricky, because `v[n]` isn't really an lvalue, as its address cannot be taken. The only place it can be used as an lvalue is on the left-hand side of an assignment. Implement unary operators on vector objects (except for logical not on a vector mask, which will be covered in a future commit for boolean vectors). The code for lowering cir.unary for all types, in `CIRUnaryOpLowering::matchAndRewrite`, was largely rewritten. Support for unary `+` on non-vector pointer types was added. (It was already supported and tested in AST->ClangIR CodeGen, but was missing from ClangIR->LLVM Dialect lowering.) Add tests for all binary vector arithmetic operations other than relational operators and shift operators. There were all working after the previous vector types commit, but only addition had beet tested at the time. Co-authored-by: Bruno Cardoso Lopes <bcardosolopes@users.noreply.github.com>
This is part 2 of implementing vector types and vector operations in ClangIR, issue #284. Create new operation `cir.vec.insert`, which changes one element of an existing vector object and returns the modified vector object. The input and output vectors are prvalues; this operation does not touch memory. The assembly format and the order of the arguments match that of llvm.insertelement in the LLVM dialect, since the operations have identical semantics. Implement vector element lvalues in class `LValue`, adding member functions `getVectorAddress()`, `getVectorPointer()`, `getVectorIdx()`, and `MakeVectorElt(...)`. The assembly format for operation `cir.vec.extract` was changed to match that of llvm.extractelement in the LLVM dialect, since the operations have identical semantics. These two features, `cir.vec.insert` and vector element lvalues, are used to implement `v[n] = e`, where `v` is a vector. This is a little tricky, because `v[n]` isn't really an lvalue, as its address cannot be taken. The only place it can be used as an lvalue is on the left-hand side of an assignment. Implement unary operators on vector objects (except for logical not on a vector mask, which will be covered in a future commit for boolean vectors). The code for lowering cir.unary for all types, in `CIRUnaryOpLowering::matchAndRewrite`, was largely rewritten. Support for unary `+` on non-vector pointer types was added. (It was already supported and tested in AST->ClangIR CodeGen, but was missing from ClangIR->LLVM Dialect lowering.) Add tests for all binary vector arithmetic operations other than relational operators and shift operators. There were all working after the previous vector types commit, but only addition had beet tested at the time. Co-authored-by: Bruno Cardoso Lopes <bcardosolopes@users.noreply.github.com>
This is part 3 of implementing vector types and vector operations in ClangIR, issue #284. Create new operation `cir.vec.cmp` which implements the relational comparison operators (`== != < > <= >=`) on vector types. A new operation was created rather than reusing `cir.cmp` because the result is a vector of a signed intergral type, not a `bool`. Add CodeGen and Lowering tests for vector comparisons. Fix the floating-point comparison predicate when lowering to LLVM. To handle NaN values correctly, the comparisons need to be ordered rather than unordered. (Except for `!=`, which needs to be unordered.) For example, "ueq" was changed to "oeq".
This is part 4 of implementing vector types and vector operations in ClangIR, issue #284. This change has three small additions. Implement a "vector splat" conversion, which converts a scalar into vector, initializing all the elements of the vector with the scalar. Implement incomplete initialization of a vector, where the number of explicit initializers is less than the number of elements in the vector. The rest of the elements are implicitly zero initialized. Implement conversions between different vector types. The language rules require that the two types be the same size (in bytes, not necessarily in the number of elements). These conversions are always implemented with a bitcast. The first two changes only required changes to the AST -> ClangIR code gen. There are no changes to the ClangIR dialect, so no changes to the LLVM lowering were needed. The third part only required a change to a validation rule. The code to implement a vector bitcast was already present. The compiler just needed to stop rejecting it as invalid ClangIR.
Implement `__builtin_shufflevector` and `__builtin_convertvector` in ClangIR. This change contributes to the implemention of issue #284. `__builtin_convertvector` is implemented as a cast. LLVM IR uses the same instructions for arithmetic conversions of both individual scalars and entire vectors. So ClangIR does the same. The code for handling conversions, in both CodeGen and Lowering, is cleaned up to correctly handle vector types. To simplify the lowering code and avoid `if (type.isa<VectorType>())` statements everywhere, the utility function `elementTypeIfVector` was added to `LowerToLLVM.cpp`. `__builtin_shufflevector` has two forms, only one of which appears to be documented. The documented form, which takes a variable-sized list of integer constants for the indices, is implemented with the new ClangIR operation `cir.vec.shuffle.ints`. This operation is lowered to the `llvm.shufflevector` op. The undocumented form, which gets the indices from a vector operand, is implemented with the new ClangIR operation `cir.vec.shuffle.vec`. LLVM IR does not have an instruction for this, so it gets lowered to a long series of `llvm.extractelement` and `llvm.insertelement` operations.
This is the final commit for issue #284. Vector types other than GNU vector types will be covered by other yet-to-be-created issues. Now that GNU vector types (the ones defined via the vector_size attribute) are implemented, do a final cleanup of the assertions and other checks related to vector types. Remove `UnimplementedFeature::cirVectorType()`. Deal with the remaining calls to that function. When the that is not yet implemented has to do with Arm SVE vectors, the assert was changed to `UnimplementedFeature::scalableVectors()` instead. The assertion was removed in cases where the code correctly handle GNU vector types. While cleaning up the assertion checks, I noticed that BinOp handling of vector types wasn't quite complete. Any special handling for integer or floating-point types wasn't happening when the operands were vector types. To fix this, split `BinOpInfo::Ty` into two fields, `FullType` and `CompType`. `FullType` is the type of the operands. `CompType` is normally the same as `FullType`, but is the element type when `FullType` is a vector type.
This is the first part of implementing vector types and vector operations in ClangIR, issue llvm#284. This is enough to compile this test program. I haven't tried to do anything beyond that yet. ``` typedef int int4 __attribute__((vector_size(16))); int main(int argc, char** argv) { int4 a = { 1, argc, argc + 1, 4 }; int4 b = { 5, argc + 2, argc + 3, 8 }; int4 c = a + b; return c[1]; } ``` This change includes: * Fixed-sized vector types which are parameterized on the element type and the number of elements. For example, `!cir.vector<s32i x 4>`. (No scalable vector types yet; those will come later.) * New operation `cir.vec` which creates an object of a vector type with the given operands. * New operation `cir.vec_elem` which extracts an element from a vector. (The array subscript operation doesn't work here because the result is an rvalue, not an lvalue.) * Basic binary arithmetic operations on vector types, though only addition has been tested. There are no unary operators, comparison operators, casts, or shuffle operations yet. Those will all come later.
This is part 2 of implementing vector types and vector operations in ClangIR, issue llvm#284. Create new operation `cir.vec.insert`, which changes one element of an existing vector object and returns the modified vector object. The input and output vectors are prvalues; this operation does not touch memory. The assembly format and the order of the arguments match that of llvm.insertelement in the LLVM dialect, since the operations have identical semantics. Implement vector element lvalues in class `LValue`, adding member functions `getVectorAddress()`, `getVectorPointer()`, `getVectorIdx()`, and `MakeVectorElt(...)`. The assembly format for operation `cir.vec.extract` was changed to match that of llvm.extractelement in the LLVM dialect, since the operations have identical semantics. These two features, `cir.vec.insert` and vector element lvalues, are used to implement `v[n] = e`, where `v` is a vector. This is a little tricky, because `v[n]` isn't really an lvalue, as its address cannot be taken. The only place it can be used as an lvalue is on the left-hand side of an assignment. Implement unary operators on vector objects (except for logical not on a vector mask, which will be covered in a future commit for boolean vectors). The code for lowering cir.unary for all types, in `CIRUnaryOpLowering::matchAndRewrite`, was largely rewritten. Support for unary `+` on non-vector pointer types was added. (It was already supported and tested in AST->ClangIR CodeGen, but was missing from ClangIR->LLVM Dialect lowering.) Add tests for all binary vector arithmetic operations other than relational operators and shift operators. There were all working after the previous vector types commit, but only addition had beet tested at the time. Co-authored-by: Bruno Cardoso Lopes <bcardosolopes@users.noreply.github.com>
This is part 3 of implementing vector types and vector operations in ClangIR, issue llvm#284. Create new operation `cir.vec.cmp` which implements the relational comparison operators (`== != < > <= >=`) on vector types. A new operation was created rather than reusing `cir.cmp` because the result is a vector of a signed intergral type, not a `bool`. Add CodeGen and Lowering tests for vector comparisons. Fix the floating-point comparison predicate when lowering to LLVM. To handle NaN values correctly, the comparisons need to be ordered rather than unordered. (Except for `!=`, which needs to be unordered.) For example, "ueq" was changed to "oeq".
This is part 4 of implementing vector types and vector operations in ClangIR, issue llvm#284. This change has three small additions. Implement a "vector splat" conversion, which converts a scalar into vector, initializing all the elements of the vector with the scalar. Implement incomplete initialization of a vector, where the number of explicit initializers is less than the number of elements in the vector. The rest of the elements are implicitly zero initialized. Implement conversions between different vector types. The language rules require that the two types be the same size (in bytes, not necessarily in the number of elements). These conversions are always implemented with a bitcast. The first two changes only required changes to the AST -> ClangIR code gen. There are no changes to the ClangIR dialect, so no changes to the LLVM lowering were needed. The third part only required a change to a validation rule. The code to implement a vector bitcast was already present. The compiler just needed to stop rejecting it as invalid ClangIR.
Implement `__builtin_shufflevector` and `__builtin_convertvector` in ClangIR. This change contributes to the implemention of issue llvm#284. `__builtin_convertvector` is implemented as a cast. LLVM IR uses the same instructions for arithmetic conversions of both individual scalars and entire vectors. So ClangIR does the same. The code for handling conversions, in both CodeGen and Lowering, is cleaned up to correctly handle vector types. To simplify the lowering code and avoid `if (type.isa<VectorType>())` statements everywhere, the utility function `elementTypeIfVector` was added to `LowerToLLVM.cpp`. `__builtin_shufflevector` has two forms, only one of which appears to be documented. The documented form, which takes a variable-sized list of integer constants for the indices, is implemented with the new ClangIR operation `cir.vec.shuffle.ints`. This operation is lowered to the `llvm.shufflevector` op. The undocumented form, which gets the indices from a vector operand, is implemented with the new ClangIR operation `cir.vec.shuffle.vec`. LLVM IR does not have an instruction for this, so it gets lowered to a long series of `llvm.extractelement` and `llvm.insertelement` operations.
This is the final commit for issue llvm#284. Vector types other than GNU vector types will be covered by other yet-to-be-created issues. Now that GNU vector types (the ones defined via the vector_size attribute) are implemented, do a final cleanup of the assertions and other checks related to vector types. Remove `UnimplementedFeature::cirVectorType()`. Deal with the remaining calls to that function. When the that is not yet implemented has to do with Arm SVE vectors, the assert was changed to `UnimplementedFeature::scalableVectors()` instead. The assertion was removed in cases where the code correctly handle GNU vector types. While cleaning up the assertion checks, I noticed that BinOp handling of vector types wasn't quite complete. Any special handling for integer or floating-point types wasn't happening when the operands were vector types. To fix this, split `BinOpInfo::Ty` into two fields, `FullType` and `CompType`. `FullType` is the type of the operands. `CompType` is normally the same as `FullType`, but is the element type when `FullType` is a vector type.
This is the first part of implementing vector types and vector operations in ClangIR, issue llvm#284. This is enough to compile this test program. I haven't tried to do anything beyond that yet. ``` typedef int int4 __attribute__((vector_size(16))); int main(int argc, char** argv) { int4 a = { 1, argc, argc + 1, 4 }; int4 b = { 5, argc + 2, argc + 3, 8 }; int4 c = a + b; return c[1]; } ``` This change includes: * Fixed-sized vector types which are parameterized on the element type and the number of elements. For example, `!cir.vector<s32i x 4>`. (No scalable vector types yet; those will come later.) * New operation `cir.vec` which creates an object of a vector type with the given operands. * New operation `cir.vec_elem` which extracts an element from a vector. (The array subscript operation doesn't work here because the result is an rvalue, not an lvalue.) * Basic binary arithmetic operations on vector types, though only addition has been tested. There are no unary operators, comparison operators, casts, or shuffle operations yet. Those will all come later.
This is part 2 of implementing vector types and vector operations in ClangIR, issue llvm#284. Create new operation `cir.vec.insert`, which changes one element of an existing vector object and returns the modified vector object. The input and output vectors are prvalues; this operation does not touch memory. The assembly format and the order of the arguments match that of llvm.insertelement in the LLVM dialect, since the operations have identical semantics. Implement vector element lvalues in class `LValue`, adding member functions `getVectorAddress()`, `getVectorPointer()`, `getVectorIdx()`, and `MakeVectorElt(...)`. The assembly format for operation `cir.vec.extract` was changed to match that of llvm.extractelement in the LLVM dialect, since the operations have identical semantics. These two features, `cir.vec.insert` and vector element lvalues, are used to implement `v[n] = e`, where `v` is a vector. This is a little tricky, because `v[n]` isn't really an lvalue, as its address cannot be taken. The only place it can be used as an lvalue is on the left-hand side of an assignment. Implement unary operators on vector objects (except for logical not on a vector mask, which will be covered in a future commit for boolean vectors). The code for lowering cir.unary for all types, in `CIRUnaryOpLowering::matchAndRewrite`, was largely rewritten. Support for unary `+` on non-vector pointer types was added. (It was already supported and tested in AST->ClangIR CodeGen, but was missing from ClangIR->LLVM Dialect lowering.) Add tests for all binary vector arithmetic operations other than relational operators and shift operators. There were all working after the previous vector types commit, but only addition had beet tested at the time. Co-authored-by: Bruno Cardoso Lopes <bcardosolopes@users.noreply.github.com>
This is part 3 of implementing vector types and vector operations in ClangIR, issue llvm#284. Create new operation `cir.vec.cmp` which implements the relational comparison operators (`== != < > <= >=`) on vector types. A new operation was created rather than reusing `cir.cmp` because the result is a vector of a signed intergral type, not a `bool`. Add CodeGen and Lowering tests for vector comparisons. Fix the floating-point comparison predicate when lowering to LLVM. To handle NaN values correctly, the comparisons need to be ordered rather than unordered. (Except for `!=`, which needs to be unordered.) For example, "ueq" was changed to "oeq".
This is part 4 of implementing vector types and vector operations in ClangIR, issue llvm#284. This change has three small additions. Implement a "vector splat" conversion, which converts a scalar into vector, initializing all the elements of the vector with the scalar. Implement incomplete initialization of a vector, where the number of explicit initializers is less than the number of elements in the vector. The rest of the elements are implicitly zero initialized. Implement conversions between different vector types. The language rules require that the two types be the same size (in bytes, not necessarily in the number of elements). These conversions are always implemented with a bitcast. The first two changes only required changes to the AST -> ClangIR code gen. There are no changes to the ClangIR dialect, so no changes to the LLVM lowering were needed. The third part only required a change to a validation rule. The code to implement a vector bitcast was already present. The compiler just needed to stop rejecting it as invalid ClangIR.
Implement `__builtin_shufflevector` and `__builtin_convertvector` in ClangIR. This change contributes to the implemention of issue llvm#284. `__builtin_convertvector` is implemented as a cast. LLVM IR uses the same instructions for arithmetic conversions of both individual scalars and entire vectors. So ClangIR does the same. The code for handling conversions, in both CodeGen and Lowering, is cleaned up to correctly handle vector types. To simplify the lowering code and avoid `if (type.isa<VectorType>())` statements everywhere, the utility function `elementTypeIfVector` was added to `LowerToLLVM.cpp`. `__builtin_shufflevector` has two forms, only one of which appears to be documented. The documented form, which takes a variable-sized list of integer constants for the indices, is implemented with the new ClangIR operation `cir.vec.shuffle.ints`. This operation is lowered to the `llvm.shufflevector` op. The undocumented form, which gets the indices from a vector operand, is implemented with the new ClangIR operation `cir.vec.shuffle.vec`. LLVM IR does not have an instruction for this, so it gets lowered to a long series of `llvm.extractelement` and `llvm.insertelement` operations.
This is the final commit for issue llvm#284. Vector types other than GNU vector types will be covered by other yet-to-be-created issues. Now that GNU vector types (the ones defined via the vector_size attribute) are implemented, do a final cleanup of the assertions and other checks related to vector types. Remove `UnimplementedFeature::cirVectorType()`. Deal with the remaining calls to that function. When the that is not yet implemented has to do with Arm SVE vectors, the assert was changed to `UnimplementedFeature::scalableVectors()` instead. The assertion was removed in cases where the code correctly handle GNU vector types. While cleaning up the assertion checks, I noticed that BinOp handling of vector types wasn't quite complete. Any special handling for integer or floating-point types wasn't happening when the operands were vector types. To fix this, split `BinOpInfo::Ty` into two fields, `FullType` and `CompType`. `FullType` is the type of the operands. `CompType` is normally the same as `FullType`, but is the element type when `FullType` is a vector type.
This is the first part of implementing vector types and vector operations in ClangIR, issue llvm#284. This is enough to compile this test program. I haven't tried to do anything beyond that yet. ``` typedef int int4 __attribute__((vector_size(16))); int main(int argc, char** argv) { int4 a = { 1, argc, argc + 1, 4 }; int4 b = { 5, argc + 2, argc + 3, 8 }; int4 c = a + b; return c[1]; } ``` This change includes: * Fixed-sized vector types which are parameterized on the element type and the number of elements. For example, `!cir.vector<s32i x 4>`. (No scalable vector types yet; those will come later.) * New operation `cir.vec` which creates an object of a vector type with the given operands. * New operation `cir.vec_elem` which extracts an element from a vector. (The array subscript operation doesn't work here because the result is an rvalue, not an lvalue.) * Basic binary arithmetic operations on vector types, though only addition has been tested. There are no unary operators, comparison operators, casts, or shuffle operations yet. Those will all come later.
This is part 2 of implementing vector types and vector operations in ClangIR, issue llvm#284. Create new operation `cir.vec.insert`, which changes one element of an existing vector object and returns the modified vector object. The input and output vectors are prvalues; this operation does not touch memory. The assembly format and the order of the arguments match that of llvm.insertelement in the LLVM dialect, since the operations have identical semantics. Implement vector element lvalues in class `LValue`, adding member functions `getVectorAddress()`, `getVectorPointer()`, `getVectorIdx()`, and `MakeVectorElt(...)`. The assembly format for operation `cir.vec.extract` was changed to match that of llvm.extractelement in the LLVM dialect, since the operations have identical semantics. These two features, `cir.vec.insert` and vector element lvalues, are used to implement `v[n] = e`, where `v` is a vector. This is a little tricky, because `v[n]` isn't really an lvalue, as its address cannot be taken. The only place it can be used as an lvalue is on the left-hand side of an assignment. Implement unary operators on vector objects (except for logical not on a vector mask, which will be covered in a future commit for boolean vectors). The code for lowering cir.unary for all types, in `CIRUnaryOpLowering::matchAndRewrite`, was largely rewritten. Support for unary `+` on non-vector pointer types was added. (It was already supported and tested in AST->ClangIR CodeGen, but was missing from ClangIR->LLVM Dialect lowering.) Add tests for all binary vector arithmetic operations other than relational operators and shift operators. There were all working after the previous vector types commit, but only addition had beet tested at the time. Co-authored-by: Bruno Cardoso Lopes <bcardosolopes@users.noreply.github.com>
This is part 3 of implementing vector types and vector operations in ClangIR, issue llvm#284. Create new operation `cir.vec.cmp` which implements the relational comparison operators (`== != < > <= >=`) on vector types. A new operation was created rather than reusing `cir.cmp` because the result is a vector of a signed intergral type, not a `bool`. Add CodeGen and Lowering tests for vector comparisons. Fix the floating-point comparison predicate when lowering to LLVM. To handle NaN values correctly, the comparisons need to be ordered rather than unordered. (Except for `!=`, which needs to be unordered.) For example, "ueq" was changed to "oeq".
This is part 4 of implementing vector types and vector operations in ClangIR, issue llvm#284. This change has three small additions. Implement a "vector splat" conversion, which converts a scalar into vector, initializing all the elements of the vector with the scalar. Implement incomplete initialization of a vector, where the number of explicit initializers is less than the number of elements in the vector. The rest of the elements are implicitly zero initialized. Implement conversions between different vector types. The language rules require that the two types be the same size (in bytes, not necessarily in the number of elements). These conversions are always implemented with a bitcast. The first two changes only required changes to the AST -> ClangIR code gen. There are no changes to the ClangIR dialect, so no changes to the LLVM lowering were needed. The third part only required a change to a validation rule. The code to implement a vector bitcast was already present. The compiler just needed to stop rejecting it as invalid ClangIR.
Implement `__builtin_shufflevector` and `__builtin_convertvector` in ClangIR. This change contributes to the implemention of issue llvm#284. `__builtin_convertvector` is implemented as a cast. LLVM IR uses the same instructions for arithmetic conversions of both individual scalars and entire vectors. So ClangIR does the same. The code for handling conversions, in both CodeGen and Lowering, is cleaned up to correctly handle vector types. To simplify the lowering code and avoid `if (type.isa<VectorType>())` statements everywhere, the utility function `elementTypeIfVector` was added to `LowerToLLVM.cpp`. `__builtin_shufflevector` has two forms, only one of which appears to be documented. The documented form, which takes a variable-sized list of integer constants for the indices, is implemented with the new ClangIR operation `cir.vec.shuffle.ints`. This operation is lowered to the `llvm.shufflevector` op. The undocumented form, which gets the indices from a vector operand, is implemented with the new ClangIR operation `cir.vec.shuffle.vec`. LLVM IR does not have an instruction for this, so it gets lowered to a long series of `llvm.extractelement` and `llvm.insertelement` operations.
This is the final commit for issue llvm#284. Vector types other than GNU vector types will be covered by other yet-to-be-created issues. Now that GNU vector types (the ones defined via the vector_size attribute) are implemented, do a final cleanup of the assertions and other checks related to vector types. Remove `UnimplementedFeature::cirVectorType()`. Deal with the remaining calls to that function. When the that is not yet implemented has to do with Arm SVE vectors, the assert was changed to `UnimplementedFeature::scalableVectors()` instead. The assertion was removed in cases where the code correctly handle GNU vector types. While cleaning up the assertion checks, I noticed that BinOp handling of vector types wasn't quite complete. Any special handling for integer or floating-point types wasn't happening when the operands were vector types. To fix this, split `BinOpInfo::Ty` into two fields, `FullType` and `CompType`. `FullType` is the type of the operands. `CompType` is normally the same as `FullType`, but is the element type when `FullType` is a vector type.
This is the first part of implementing vector types and vector operations in ClangIR, issue #284. This is enough to compile this test program. I haven't tried to do anything beyond that yet. ``` typedef int int4 __attribute__((vector_size(16))); int main(int argc, char** argv) { int4 a = { 1, argc, argc + 1, 4 }; int4 b = { 5, argc + 2, argc + 3, 8 }; int4 c = a + b; return c[1]; } ``` This change includes: * Fixed-sized vector types which are parameterized on the element type and the number of elements. For example, `!cir.vector<s32i x 4>`. (No scalable vector types yet; those will come later.) * New operation `cir.vec` which creates an object of a vector type with the given operands. * New operation `cir.vec_elem` which extracts an element from a vector. (The array subscript operation doesn't work here because the result is an rvalue, not an lvalue.) * Basic binary arithmetic operations on vector types, though only addition has been tested. There are no unary operators, comparison operators, casts, or shuffle operations yet. Those will all come later.
This is part 2 of implementing vector types and vector operations in ClangIR, issue #284. Create new operation `cir.vec.insert`, which changes one element of an existing vector object and returns the modified vector object. The input and output vectors are prvalues; this operation does not touch memory. The assembly format and the order of the arguments match that of llvm.insertelement in the LLVM dialect, since the operations have identical semantics. Implement vector element lvalues in class `LValue`, adding member functions `getVectorAddress()`, `getVectorPointer()`, `getVectorIdx()`, and `MakeVectorElt(...)`. The assembly format for operation `cir.vec.extract` was changed to match that of llvm.extractelement in the LLVM dialect, since the operations have identical semantics. These two features, `cir.vec.insert` and vector element lvalues, are used to implement `v[n] = e`, where `v` is a vector. This is a little tricky, because `v[n]` isn't really an lvalue, as its address cannot be taken. The only place it can be used as an lvalue is on the left-hand side of an assignment. Implement unary operators on vector objects (except for logical not on a vector mask, which will be covered in a future commit for boolean vectors). The code for lowering cir.unary for all types, in `CIRUnaryOpLowering::matchAndRewrite`, was largely rewritten. Support for unary `+` on non-vector pointer types was added. (It was already supported and tested in AST->ClangIR CodeGen, but was missing from ClangIR->LLVM Dialect lowering.) Add tests for all binary vector arithmetic operations other than relational operators and shift operators. There were all working after the previous vector types commit, but only addition had beet tested at the time. Co-authored-by: Bruno Cardoso Lopes <bcardosolopes@users.noreply.github.com>
This is part 3 of implementing vector types and vector operations in ClangIR, issue #284. Create new operation `cir.vec.cmp` which implements the relational comparison operators (`== != < > <= >=`) on vector types. A new operation was created rather than reusing `cir.cmp` because the result is a vector of a signed intergral type, not a `bool`. Add CodeGen and Lowering tests for vector comparisons. Fix the floating-point comparison predicate when lowering to LLVM. To handle NaN values correctly, the comparisons need to be ordered rather than unordered. (Except for `!=`, which needs to be unordered.) For example, "ueq" was changed to "oeq".
This is part 4 of implementing vector types and vector operations in ClangIR, issue #284. This change has three small additions. Implement a "vector splat" conversion, which converts a scalar into vector, initializing all the elements of the vector with the scalar. Implement incomplete initialization of a vector, where the number of explicit initializers is less than the number of elements in the vector. The rest of the elements are implicitly zero initialized. Implement conversions between different vector types. The language rules require that the two types be the same size (in bytes, not necessarily in the number of elements). These conversions are always implemented with a bitcast. The first two changes only required changes to the AST -> ClangIR code gen. There are no changes to the ClangIR dialect, so no changes to the LLVM lowering were needed. The third part only required a change to a validation rule. The code to implement a vector bitcast was already present. The compiler just needed to stop rejecting it as invalid ClangIR.
Implement `__builtin_shufflevector` and `__builtin_convertvector` in ClangIR. This change contributes to the implemention of issue #284. `__builtin_convertvector` is implemented as a cast. LLVM IR uses the same instructions for arithmetic conversions of both individual scalars and entire vectors. So ClangIR does the same. The code for handling conversions, in both CodeGen and Lowering, is cleaned up to correctly handle vector types. To simplify the lowering code and avoid `if (type.isa<VectorType>())` statements everywhere, the utility function `elementTypeIfVector` was added to `LowerToLLVM.cpp`. `__builtin_shufflevector` has two forms, only one of which appears to be documented. The documented form, which takes a variable-sized list of integer constants for the indices, is implemented with the new ClangIR operation `cir.vec.shuffle.ints`. This operation is lowered to the `llvm.shufflevector` op. The undocumented form, which gets the indices from a vector operand, is implemented with the new ClangIR operation `cir.vec.shuffle.vec`. LLVM IR does not have an instruction for this, so it gets lowered to a long series of `llvm.extractelement` and `llvm.insertelement` operations.
This is the final commit for issue #284. Vector types other than GNU vector types will be covered by other yet-to-be-created issues. Now that GNU vector types (the ones defined via the vector_size attribute) are implemented, do a final cleanup of the assertions and other checks related to vector types. Remove `UnimplementedFeature::cirVectorType()`. Deal with the remaining calls to that function. When the that is not yet implemented has to do with Arm SVE vectors, the assert was changed to `UnimplementedFeature::scalableVectors()` instead. The assertion was removed in cases where the code correctly handle GNU vector types. While cleaning up the assertion checks, I noticed that BinOp handling of vector types wasn't quite complete. Any special handling for integer or floating-point types wasn't happening when the operands were vector types. To fix this, split `BinOpInfo::Ty` into two fields, `FullType` and `CompType`. `FullType` is the type of the operands. `CompType` is normally the same as `FullType`, but is the element type when `FullType` is a vector type.
Example:
__attribute__((ext_vector_type(size)))
. This should be mapped to a first class type in CIR.The text was updated successfully, but these errors were encountered: