-
Notifications
You must be signed in to change notification settings - Fork 88
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
Fixed length attributes #176
Comments
Yes, we can have the compiler derive types like I personally don't think it is worth the effort because this approach cannot transit to what RVV is designed for, which the vector length can be scalable. I think the computations should rely on |
I agree to your comment, that this will not transition into an VLA approach. But it can help lower the burden of transitioning from current SIMD solutions which are vector length specific to RVV. ARM has solved this through such attributes: |
Sure, I agree with you this would help SIMD users to adapt RVV. Just added this topic to next Monday's open meeting. |
I posted the first patch to support something like That patch only supports the command line option to specify the number of bits in a vector. It does not add the attribute yet. |
Bigger patch has been posted https://reviews.llvm.org/D145088 to support LMUL=1 types. |
…sve_vector_bits. This allows the user to set the size of the scalable vector so they can be used in structs and as the type of global variables. This works by representing the type as a fixed vector instead of a scalable vector in IR. Conversions to and from scalable vectors are made where necessary like function arguments/returns and intrinsics. This features has been requested here riscv-non-isa/rvv-intrinsic-doc#176 I know arm_sve_vector_bits is used by the Eigen library so this could be used to port Eigen to RVV. This patch adds a new preprocessor define `__riscv_v_fixed_vlen` that is set when -mrvv_vector_bits is passed on the command line. The code is largely based on the AArch64 code. A lot of code was copy/pasted and then modiied to RVV. There may be some opportunities for sharing. This first patch only supports the LMUL=1 types. Additional changes will be needed to support other LMULs. I have also not supported mask vectors. Differential Revision: https://reviews.llvm.org/D145088
I think there is an option to support porting old fixed size code to rvv, while keeping the generated machine code scalable. You don't even need a new attributes, if you can rely on the compiler eliminating redundant vector load/stores, which clang and gcc currently don't do. Say you want to port the following code, that uses both 128 bit wide SSE2 intrinsics and 256 wide AVX2 intrinsics, to all Zvl64b compatible processors ( typedef struct { __m128i a; __m256i b; } S;
S add(S x, S y) {
return (S){ _mm_add_epi8(x.a, y.a), _mm256_add_epi8(x.b, y.b) };
} This could be ported using: typedef struct { uint8_t x[16]; } __m128i;
typedef struct { uint8_t x[32]; } __m256i;
static inline __m128i
_mm_add_epi32(__m128i a, __m128i b) {
__m128i res;
vuint8m2_t A = __riscv_vle8_v_u8m2((void*)&a.x, 16);
vuint8m2_t B = __riscv_vle8_v_u8m2((void*)&b.x, 16);
__riscv_vse8_v_u8m2((void*)&res, __riscv_vadd_vv_u8m2(A, B, 16), 16);
return res;
}
static inline __m256i
_mm256_add_epi32(__m256i a, __m256i b) {
__m256i res;
vuint8m4_t A = __riscv_vle8_v_u8m4((void*)&a.x, 32);
vuint8m4_t B = __riscv_vle8_v_u8m4((void*)&b.x, 32);
__riscv_vse8_v_u8m4((void*)&res, __riscv_vadd_vv_u8m4(A, B, 32), 32);
return res;
} See how the above uses The problem with the above is that it doesn't get optimized properly at all with current compilers: https://godbolt.org/z/EEjfxvMcd But I'd expect that future compiler versions will be able to do so, as they are already able to optimize away redundant SSE/AVX load/stores: https://godbolt.org/z/Ghs3x388P If this isn't the case, you could still create special attributes that would look similar to the following: typedef struct {
vuint32m1_t [[rvv_vl(4)]] a;
vuint32m2_t [[rvv_vl(8)]] b;
} S;
S add(S x, S y) {
return (S){ vadd_vv_u32m1(x.a, y.a), vadd_vv_u32m2(x.b, y.b) };
} Here |
This can also be ported as
Which is the code from clang's emmintrin.h and avx2intrin.h headers. https://godbolt.org/z/93qfjez4e There has been some work in clang to add things like |
This was just an example, but the same approach would work the other more complex instructions. Wouldn't your comment also apply to
This feels like it's currently very limited, is integrating all of the intrinsics into a platform agnostic abstraction a thing clang aims to do? Edit: Also, would your code compiled for |
riscv_rvv_vector_bits allows you to tell the compiler exactly what VLEN your CPU has. Using You could get some of the same effect from using
I think it's primarily just the things that have a single intrinsic generic IR representation that can easily be supported by any target. It's probably not going to have something weird like X86's psadbw for example. For the most part RISC-V doesn't have weird instructions, so not being able to target them may not be a big deal?
My example used |
FTR attribute support in gcc landed: https://gcc.gnu.org/pipermail/gcc-patches/2024-March/648204.html
|
Has there been consideration for an attribute to specify a fixed length for vector and mask types?
A reference of such a solution could be ACLE vector bits attribute.
Background is that many existing SIMD libraries were build around fixed length vectors, and use those in places like classes and structs that are not possible with the sizeless types of the rvv intrinsics. Adding an RVV port is very tricky at least in those cases. To lower the entry barrier for RISC-V V, I could imagine this would be a good step.
The text was updated successfully, but these errors were encountered: