RISC-V: Ensure vector args and return use function stack to pass [PR110119]

The V2 patch address comments from Juzhe, thanks.

Hi,

The reason for this bug is that in the case where the vector register is set
to a fixed length (with `--param=riscv-autovec-preference=fixed-vlmax` option),
TARGET_PASS_BY_REFERENCE thinks that variables of type vint32m1 can be passed
through two scalar registers, but when GCC calls FUNCTION_VALUE (call function
riscv_get_arg_info inside) it returns NULL_RTX. These two functions are not
unified. The current treatment is to pass all vector arguments and returns
through the function stack, and a new calling convention for vector registers
will be added in the future.

https://github.com/riscv-non-isa/riscv-elf-psabi-doc/
126fa71997

Best,
Lehua

gcc/ChangeLog:
	PR target/110119
	* config/riscv/riscv.cc (riscv_get_arg_info): Return NULL_RTX for vector mode
	(riscv_pass_by_reference): Return true for vector mode

gcc/testsuite/ChangeLog:
	PR target/110119
	* gcc.target/riscv/rvv/base/pr110119-1.c: New test.
	* gcc.target/riscv/rvv/base/pr110119-2.c: New test.
This commit is contained in:
Lehua Ding 2023-06-14 19:56:11 +08:00 committed by Pan Li
parent 41738a1b3f
commit 0ec3fbb590
3 changed files with 64 additions and 5 deletions

View file

@ -3915,13 +3915,13 @@ riscv_get_arg_info (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum,
riscv_pass_in_vector_p (type);
}
/* TODO: Currently, it will cause an ICE for --param
riscv-autovec-preference=fixed-vlmax. So, we just return NULL_RTX here
let GCC generate loads/stores. Ideally, we should either warn the user not
to use an RVV vector type as function argument or support the calling
convention directly. */
/* All current vector arguments and return values are passed through the
function stack. Ideally, we should either warn the user not to use an RVV
vector type as function argument or support a calling convention
with better performance. */
if (riscv_v_ext_mode_p (mode))
return NULL_RTX;
if (named)
{
riscv_aggregate_field fields[2];
@ -4106,6 +4106,13 @@ riscv_pass_by_reference (cumulative_args_t cum_v, const function_arg_info &arg)
return false;
}
/* All current vector arguments and return values are passed through the
function stack. Ideally, we should either warn the user not to use an RVV
vector type as function argument or support a calling convention
with better performance. */
if (riscv_v_ext_mode_p (arg.mode))
return true;
/* Pass by reference if the data do not fit in two integer registers. */
return !IN_RANGE (size, 0, 2 * UNITS_PER_WORD);
}

View file

@ -0,0 +1,26 @@
/* { dg-do compile } */
/* { dg-options "-march=rv64gcv --param=riscv-autovec-preference=fixed-vlmax" } */
#include "riscv_vector.h"
typedef int8_t vnx2qi __attribute__ ((vector_size (2)));
__attribute__ ((noipa)) vnx2qi
f_vnx2qi (int8_t a, int8_t b, int8_t *out)
{
vnx2qi v = {a, b};
return v;
}
__attribute__ ((noipa)) vnx2qi
f_vnx2qi_2 (vnx2qi a, int8_t *out)
{
return a;
}
__attribute__ ((noipa)) vint32m1_t
f_vint32m1 (int8_t *a, int8_t *out)
{
vint32m1_t v = *(vint32m1_t *) a;
return v;
}

View file

@ -0,0 +1,26 @@
/* { dg-do compile } */
/* { dg-options "-march=rv64gczve32x --param=riscv-autovec-preference=fixed-vlmax" } */
#include <stdint.h>
#include "riscv_vector.h"
__attribute__ ((noipa)) vint32m1x3_t
foo1 (int32_t *in, int vl)
{
vint32m1x3_t v = __riscv_vlseg3e32_v_i32m1x3 (in, vl);
return v;
}
__attribute__ ((noipa)) void
foo2 (vint32m1x3_t a, int32_t *out, int vl)
{
__riscv_vsseg3e32_v_i32m1x3 (out, a, vl);
}
__attribute__ ((noipa)) vint32m1x3_t
foo3 (vint32m1x3_t a, int32_t *out, int32_t *in, int vl)
{
__riscv_vsseg3e32_v_i32m1x3 (out, a, vl);
vint32m1x3_t v = __riscv_vlseg3e32_v_i32m1x3 (in, vl);
return v;
}