From: wangzicong Date: Thu, 30 Apr 2026 13:23:07 +0000 (+0800) Subject: RISC-V: Make tuple vector not tieable to some modes. X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8add8bccdcdd40103c320648d00a07c54d97160d;p=thirdparty%2Fgcc.git RISC-V: Make tuple vector not tieable to some modes. This patch makes riscv tuple modes not tieable to non-tuple modes. Without this patch some unnecessary type conversions may occur, especially when zvl is specified. E.g. RVVMF2x4HI and RVVM2DI are tieable in gcc trunk, and when extracting an inner vector mode RVVMF2HI from RVVMF2x4HI and zvl is specified, it will be converted to DI, which is not expected. But with same inner modes, e.g. RVVM1x4QI and RVVM1QI, they should be tieable. PR target/124448 gcc/ChangeLog: * config/riscv/riscv.cc (riscv_modes_tieable_p): Make tuple modes not tieable to some modes. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/autovec/pr124448.c: New test. Signed-off-by: wangzicong --- diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 3fae7b5b9f0..108f1c4b3cf 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -10992,6 +10992,33 @@ riscv_modes_tieable_p (machine_mode mode1, machine_mode mode2) E.g. V2SI and DI are not tieable. */ if (riscv_vector_mode_p (mode1) != riscv_vector_mode_p (mode2)) return false; + + /* We don't allow tuple vector modes to be tied to any vector mode + that has different inner mode. It may cause unnecessary type + conversions. + E.g. RVVMF2x4HI and RVVM2DI are not tieable, but + RVVM1x4QI and RVVM1QI are tieable. */ + if (riscv_tuple_mode_p (mode1) || riscv_tuple_mode_p (mode2)) + { + machine_mode subpart_mode1, subpart_mode2; + if (riscv_tuple_mode_p (mode1)) + { + subpart_mode1 = riscv_vector::get_subpart_mode (mode1); + subpart_mode1 = GET_MODE_INNER (subpart_mode1); + } + else + subpart_mode1 = GET_MODE_INNER (mode1); + if (riscv_tuple_mode_p (mode2)) + { + subpart_mode2 = riscv_vector::get_subpart_mode (mode2); + subpart_mode2 = GET_MODE_INNER (subpart_mode2); + } + else + subpart_mode2 = GET_MODE_INNER (mode2); + if (subpart_mode1 != subpart_mode2) + return false; + } + return (mode1 == mode2 || !(GET_MODE_CLASS (mode1) == MODE_FLOAT && GET_MODE_CLASS (mode2) == MODE_FLOAT)); diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr124448.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr124448.c new file mode 100644 index 00000000000..c90743378ed --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr124448.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gcv_zvl128b -mabi=lp64d -O3 -mrvv-vector-bits=zvl -fdump-rtl-vregs" } */ + +typedef short int16_t; + +void dct( int16_t d[16], int16_t dct[16] ) +{ + int16_t tmp[16]; + for( int i = 0; i < 4; i++ ) + { + int s03 = d[i*4+0] + d[i*4+3]; + int s12 = d[i*4+1] + d[i*4+2]; + int d03 = d[i*4+0] - d[i*4+3]; + int d12 = d[i*4+1] - d[i*4+2]; + tmp[0*4+i] = s03 + s12; + tmp[1*4+i] = 2*d03 + d12; + tmp[2*4+i] = s03 - s12; + tmp[3*4+i] = d03 - 2*d12; + } + for( int i = 0; i < 4; i++ ) + { + int s03 = tmp[i*4+0] + tmp[i*4+3]; + int s12 = tmp[i*4+1] + tmp[i*4+2]; + int d03 = tmp[i*4+0] - tmp[i*4+3]; + int d12 = tmp[i*4+1] - tmp[i*4+2]; + + dct[i*4+0] = s03 + s12; + dct[i*4+1] = 2*d03 + d12; + dct[i*4+2] = s03 - s12; + dct[i*4+3] = d03 - 2*d12; + } +} + +/* { dg-final { scan-assembler-times {vsetivli} 1 } } */ +/* { dg-final { scan-assembler-not {vslidedown\.vi} } } */ +/* { dg-final { scan-rtl-dump-not "\(subreg:RVVM2DI \(reg:RVVMF2x4HI.*\).*\)" "vregs" } } */