Question about using `__riscv_vlm_v`
Closed this issue · 2 comments
sunshaoce commented
#include <riscv_vector.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
void load(size_t N, uint8_t *Mask, int *A, int *C) {
size_t Nums;
for (size_t VL = 0; N > 0; N -= VL, A += VL, C += VL) {
VL = __riscv_vsetvl_e32m1(N);
printf("vl = %zu\n", VL);
Nums += VL;
vbool32_t M = __riscv_vlm_v_b32(Mask + (Nums - 1) / 8, VL);
vint32m1_t VA = __riscv_vle32_v_i32m1_m(M, A, VL);
__riscv_vse32_v_i32m1(C, VA, VL);
}
}
int main() {
int32_t A[10] = {1, 2, 3, 4, 5, 6, 7, 8, 19, 20};
uint8_t Mask[10 / 8] = {0b00000101, 0b11};
int32_t C[10] = {0};
load(10, Mask, A, C);
for (unsigned i = 0; i < 10; ++i)
printf("%d ", C[i]);
printf("\n");
return 0;
}
I got (elf-clang&elf-gcc spike+pk):
-------clang-------
bbl loader
vl = 4
vl = 4
vl = 2
1 0 3 0 5 0 7 0 19 20
-------gcc-------
bbl loader
vl = 4
vl = 4
vl = 2
1 0 3 0 5 0 7 0 19 20
It should be:
1 0 3 0 0 0 0 0 19 20
What is the problem?
zhongjuzhe commented
Compiler is not able to access bit-represent address (Address should be byte orient).
Here, for VLEN = 128bit, each mask you are using for e32m1 here is 4bits,
so you end up with accessing bit field memory.
If you specify SPIKE --varch=vlen:256, your program will work correctly since when for VLEN = 256, each e32m1 mask is 8bit (1byte).
If you want to run on VLEN = 128, I suggest you revise the code as follows:
https://godbolt.org/z/59Yccjq8E
I understand the RVV mask is quite confusing but I didn't have an immediate solution for that.
sunshaoce commented
Thank you very much, the problem has been solved!