Skip to content
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

Closed
bcardosolopes opened this issue Oct 23, 2023 · 6 comments
Closed

Add support for vector types #284

bcardosolopes opened this issue Oct 23, 2023 · 6 comments
Assignees
Labels
good first issue Good for newcomers

Comments

@bcardosolopes
Copy link
Member

Example: __attribute__((ext_vector_type(size))). This should be mapped to a first class type in CIR.

@bcardosolopes bcardosolopes added the good first issue Good for newcomers label Oct 23, 2023
@dkolsen-pgi
Copy link
Collaborator

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.

@bcardosolopes
Copy link
Member Author

bcardosolopes commented Nov 15, 2023

Should new operations be created for vector types? Or should the existing ops be reused?

This is a very relevant question!

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.

Right, similar to the std::simd drama with == and others. My take here:

  • BinOp already exists and isn't constrained to any type just yet (operands are AnyType). I'd say we reuse it for vector types because it only considers arith and logical operations, so at CIR level semantics are probably good enough. If along the way we find reasons to create specific ones, we incrementally work on those.
  • CmpOp is where the difference shines, I'd say we create new ops for these. We should also change the operation constraints for CmpOp to disallow types other than scalars.
  • All other vector specific relevant things (shuffle, reduce, etc) should have their own ops too (meaning, we could lower intrinsics/builtins directly to them).

@dkolsen-pgi
Copy link
Collaborator

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.

@bcardosolopes
Copy link
Member Author

bcardosolopes commented Nov 22, 2023

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 ShapedType trait, like memref and tensor do. So we could have a cir.vec<?xf32> type.

@dkolsen-pgi dkolsen-pgi self-assigned this Nov 23, 2023
@dkolsen-pgi
Copy link
Collaborator

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.

bcardosolopes pushed a commit that referenced this issue Dec 14, 2023
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.
lanza pushed a commit that referenced this issue Dec 20, 2023
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.
dkolsen-pgi added a commit to dkolsen-pgi/clangir that referenced this issue Jan 6, 2024
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.
bcardosolopes added a commit that referenced this issue Jan 16, 2024
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>
dkolsen-pgi added a commit to dkolsen-pgi/clangir that referenced this issue Jan 24, 2024
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".
lanza pushed a commit that referenced this issue Jan 29, 2024
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.
lanza pushed a commit that referenced this issue Jan 29, 2024
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>
dkolsen-pgi added a commit to dkolsen-pgi/clangir that referenced this issue Jan 31, 2024
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".
bcardosolopes pushed a commit that referenced this issue Jan 31, 2024
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".
dkolsen-pgi added a commit to dkolsen-pgi/clangir that referenced this issue Mar 1, 2024
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.
bcardosolopes pushed a commit that referenced this issue Mar 5, 2024
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.
lanza pushed a commit that referenced this issue Mar 23, 2024
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.
lanza pushed a commit that referenced this issue Mar 23, 2024
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>
lanza pushed a commit that referenced this issue Mar 23, 2024
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".
lanza pushed a commit that referenced this issue Mar 23, 2024
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.
eZWALT pushed a commit to eZWALT/clangir that referenced this issue Mar 24, 2024
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.
eZWALT pushed a commit to eZWALT/clangir that referenced this issue Mar 24, 2024
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>
lanza pushed a commit that referenced this issue Apr 29, 2024
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>
lanza pushed a commit that referenced this issue Apr 29, 2024
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".
lanza pushed a commit that referenced this issue Apr 29, 2024
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.
lanza pushed a commit that referenced this issue Apr 29, 2024
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.
lanza pushed a commit that referenced this issue Apr 29, 2024
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.
bruteforceboy pushed a commit to bruteforceboy/clangir that referenced this issue Oct 2, 2024
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.
bruteforceboy pushed a commit to bruteforceboy/clangir that referenced this issue Oct 2, 2024
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>
bruteforceboy pushed a commit to bruteforceboy/clangir that referenced this issue Oct 2, 2024
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".
bruteforceboy pushed a commit to bruteforceboy/clangir that referenced this issue Oct 2, 2024
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.
bruteforceboy pushed a commit to bruteforceboy/clangir that referenced this issue Oct 2, 2024
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.
bruteforceboy pushed a commit to bruteforceboy/clangir that referenced this issue Oct 2, 2024
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.
Hugobros3 pushed a commit to shady-gang/clangir that referenced this issue Oct 2, 2024
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.
Hugobros3 pushed a commit to shady-gang/clangir that referenced this issue Oct 2, 2024
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>
Hugobros3 pushed a commit to shady-gang/clangir that referenced this issue Oct 2, 2024
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".
Hugobros3 pushed a commit to shady-gang/clangir that referenced this issue Oct 2, 2024
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.
Hugobros3 pushed a commit to shady-gang/clangir that referenced this issue Oct 2, 2024
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.
Hugobros3 pushed a commit to shady-gang/clangir that referenced this issue Oct 2, 2024
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.
keryell pushed a commit to keryell/clangir that referenced this issue Oct 19, 2024
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.
keryell pushed a commit to keryell/clangir that referenced this issue Oct 19, 2024
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>
keryell pushed a commit to keryell/clangir that referenced this issue Oct 19, 2024
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".
keryell pushed a commit to keryell/clangir that referenced this issue Oct 19, 2024
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.
keryell pushed a commit to keryell/clangir that referenced this issue Oct 19, 2024
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.
keryell pushed a commit to keryell/clangir that referenced this issue Oct 19, 2024
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.
lanza pushed a commit that referenced this issue Nov 5, 2024
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.
lanza pushed a commit that referenced this issue Nov 5, 2024
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>
lanza pushed a commit that referenced this issue Nov 5, 2024
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".
lanza pushed a commit that referenced this issue Nov 5, 2024
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.
lanza pushed a commit that referenced this issue Nov 5, 2024
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.
lanza pushed a commit that referenced this issue Nov 5, 2024
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

2 participants