riscv-non-isa/rvv-intrinsic-doc

Question about using `__riscv_vlm_v`

Closed this issue · 2 comments

#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?

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.

Thank you very much, the problem has been solved!