can_find_related_mode_p incorrectly handled VLS (Vector Length Specific)
types by using TARGET_MIN_VLEN directly, which is in bits, instead of
converting it to bytes as required.

This patch fixes the issue by dividing TARGET_MIN_VLEN by 8 to convert
from bits to bytes when calculating the number of units for VLS modes.

The fix enables proper vectorization for several test cases:
- zve32f-1.c: Now correctly finds vector mode for SF mode in foo3,
  enabling vectorization of an additional loop.
- zve32f_zvl256b-1.c and zve32x_zvl256b-1.c: Added -mrvv-max-lmul=m2
  option to handle V8SI[2] (vector array mode) requirements during
  vectorizer analysis, which needs V16SI to pass, and V16SI was enabled
  incorrectly before.

Changes since V4:
- Fix testsuite, also triaged why changed.

gcc/ChangeLog:

        * config/riscv/riscv-selftests.cc (riscv_run_selftests): Call
        run_vectorize_related_mode_selftests.
        (test_vectorize_related_mode): New function to test
        vectorize_related_mode behavior.
        (run_vectorize_related_mode_selftests): New function to run all
        vectorize_related_mode tests.
        (run_vectorize_related_mode_vla_selftests): New function to test
        VLA modes.
        (run_vectorize_related_mode_vls_rv64gcv_selftests): New function to
        test VLS modes on rv64gcv.
        (run_vectorize_related_mode_vls_rv32gc_zve32x_zvl256b_selftests):
        New function to test VLS modes on rv32gc_zve32x_zvl256b.
        (run_vectorize_related_mode_vls_selftests): New function to run all
        VLS mode tests.
        * config/riscv/riscv-v.cc (can_find_related_mode_p): Fix VLS type
        handling by converting TARGET_MIN_VLEN from bits to bytes.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/rvv/autovec/zve32f-1.c: Update expected
        vectorization count from 2 to 3.
        * gcc.target/riscv/rvv/autovec/zve32f_zvl256b-1.c: Add
        -mrvv-max-lmul=m2 option.
        * gcc.target/riscv/rvv/autovec/zve32x_zvl256b-1.c: Add
        -mrvv-max-lmul=m2 option.
---
 gcc/config/riscv/riscv-selftests.cc           | 157 ++++++++++++++++++
 gcc/config/riscv/riscv-v.cc                   |   2 +-
 .../gcc.target/riscv/rvv/autovec/zve32f-1.c   |   2 +-
 .../riscv/rvv/autovec/zve32f_zvl256b-1.c      |   2 +-
 .../riscv/rvv/autovec/zve32x_zvl256b-1.c      |   2 +-
 5 files changed, 161 insertions(+), 4 deletions(-)

diff --git a/gcc/config/riscv/riscv-selftests.cc 
b/gcc/config/riscv/riscv-selftests.cc
index 9ca1ffee394..d8cc2858541 100644
--- a/gcc/config/riscv/riscv-selftests.cc
+++ b/gcc/config/riscv/riscv-selftests.cc
@@ -367,6 +367,162 @@ run_broadcast_selftests (void)
   BROADCAST_TEST (MODE_VECTOR_FLOAT)
 }
 
+static void
+test_vectorize_related_mode (machine_mode vec_mode, scalar_mode ele_mode,
+                            machine_mode expected)
+{
+  opt_machine_mode result = riscv_vector::vectorize_related_mode (vec_mode,
+                                                                 ele_mode, 0);
+  machine_mode result_mode = result.else_void ();
+  ASSERT_TRUE (result_mode == expected);
+}
+
+static void
+run_vectorize_related_mode_vla_selftests (void)
+{
+  riscv_selftest_arch_abi_setter rv ("rv64imafdcv", ABI_LP64D);
+  enum rvv_max_lmul_enum backup_rvv_max_lmul = rvv_max_lmul;
+  rvv_max_lmul = RVV_M1;
+
+  test_vectorize_related_mode (RVVM1QImode, SImode, RVVM1SImode);
+  test_vectorize_related_mode (RVVM2QImode, SImode, RVVM1SImode);
+  test_vectorize_related_mode (RVVM4QImode, SImode, RVVM1SImode);
+  test_vectorize_related_mode (RVVM8QImode, SImode, RVVM1SImode);
+  test_vectorize_related_mode (RVVM8QImode, DImode, RVVM1DImode);
+  test_vectorize_related_mode (RVVM8QImode, QImode, RVVM1QImode);
+  test_vectorize_related_mode (RVVM8QImode, HImode, RVVM1HImode);
+
+  rvv_max_lmul = RVV_M2;
+
+  test_vectorize_related_mode (RVVM1QImode, SImode, RVVM2SImode);
+  test_vectorize_related_mode (RVVM2QImode, SImode, RVVM2SImode);
+  test_vectorize_related_mode (RVVM4QImode, SImode, RVVM2SImode);
+  test_vectorize_related_mode (RVVM8QImode, SImode, RVVM2SImode);
+  test_vectorize_related_mode (RVVM8QImode, DImode, RVVM2DImode);
+  test_vectorize_related_mode (RVVM8QImode, QImode, RVVM2QImode);
+  test_vectorize_related_mode (RVVM8QImode, HImode, RVVM2HImode);
+
+  rvv_max_lmul = RVV_M4;
+
+  test_vectorize_related_mode (RVVM1QImode, SImode, RVVM4SImode);
+  test_vectorize_related_mode (RVVM2QImode, SImode, RVVM4SImode);
+  test_vectorize_related_mode (RVVM4QImode, SImode, RVVM4SImode);
+  test_vectorize_related_mode (RVVM8QImode, SImode, RVVM4SImode);
+  test_vectorize_related_mode (RVVM8QImode, DImode, RVVM4DImode);
+  test_vectorize_related_mode (RVVM8QImode, QImode, RVVM4QImode);
+  test_vectorize_related_mode (RVVM8QImode, HImode, RVVM4HImode);
+
+  rvv_max_lmul = RVV_M8;
+
+  test_vectorize_related_mode (RVVM1QImode, SImode, RVVM4SImode);
+  test_vectorize_related_mode (RVVM2QImode, SImode, RVVM8SImode);
+  test_vectorize_related_mode (RVVM4QImode, SImode, RVVM8SImode);
+  test_vectorize_related_mode (RVVM8QImode, SImode, RVVM8SImode);
+  test_vectorize_related_mode (RVVM8QImode, DImode, RVVM8DImode);
+  test_vectorize_related_mode (RVVM8QImode, QImode, RVVM8QImode);
+  test_vectorize_related_mode (RVVM8QImode, HImode, RVVM8HImode);
+
+  rvv_max_lmul = backup_rvv_max_lmul;
+}
+
+static void
+run_vectorize_related_mode_vls_rv64gcv_selftests ()
+{
+  enum rvv_vector_bits_enum backup_rvv_vector_bits = rvv_vector_bits;
+  rvv_vector_bits = RVV_VECTOR_BITS_SCALABLE;
+  riscv_selftest_arch_abi_setter rv ("rv64imafdcv", ABI_LP64D);
+  enum rvv_max_lmul_enum backup_rvv_max_lmul = rvv_max_lmul;
+  rvv_max_lmul = RVV_M1;
+
+  test_vectorize_related_mode (  V16QImode, QImode,   V16QImode);
+  test_vectorize_related_mode (  V16QImode, HImode,    V8HImode);
+  test_vectorize_related_mode (  V16QImode, SImode,    V4SImode);
+  test_vectorize_related_mode (  V16QImode, DImode,    V2DImode);
+
+  rvv_max_lmul = RVV_M2;
+
+  test_vectorize_related_mode (  V32QImode, QImode,   V32QImode);
+  test_vectorize_related_mode (  V32QImode, HImode,   V16HImode);
+  test_vectorize_related_mode (  V32QImode, SImode,    V8SImode);
+  test_vectorize_related_mode (  V32QImode, DImode,    V4DImode);
+
+  rvv_max_lmul = RVV_M4;
+
+  test_vectorize_related_mode (  V64QImode, QImode,   V64QImode);
+  test_vectorize_related_mode (  V64QImode, HImode,   V32HImode);
+  test_vectorize_related_mode (  V64QImode, SImode,   V16SImode);
+  test_vectorize_related_mode (  V64QImode, DImode,    V8DImode);
+
+  rvv_max_lmul = RVV_M8;
+
+  test_vectorize_related_mode ( V128QImode, QImode,  V128QImode);
+  test_vectorize_related_mode ( V128QImode, HImode,   V64HImode);
+  test_vectorize_related_mode ( V128QImode, SImode,   V32SImode);
+  test_vectorize_related_mode ( V128QImode, DImode,   V16DImode);
+
+  rvv_vector_bits = backup_rvv_vector_bits;
+  rvv_max_lmul = backup_rvv_max_lmul;
+}
+
+static void
+run_vectorize_related_mode_vls_rv32gc_zve32x_zvl256b_selftests ()
+{
+  enum rvv_vector_bits_enum backup_rvv_vector_bits = rvv_vector_bits;
+  rvv_vector_bits = RVV_VECTOR_BITS_SCALABLE;
+  riscv_selftest_arch_abi_setter rv ("rv32gc_zve32x_zvl256b", ABI_ILP32D);
+  enum rvv_max_lmul_enum backup_rvv_max_lmul = rvv_max_lmul;
+  rvv_max_lmul = RVV_M1;
+
+  test_vectorize_related_mode (  V32QImode, QImode,   V32QImode);
+  test_vectorize_related_mode (  V32QImode, HImode,   V16HImode);
+  test_vectorize_related_mode (  V32QImode, SImode,    V8SImode);
+  test_vectorize_related_mode (  V32QImode, DImode,    VOIDmode);
+
+  test_vectorize_related_mode (  V16QImode, QImode,   V16QImode);
+  test_vectorize_related_mode (  V16QImode, HImode,   V16HImode);
+  test_vectorize_related_mode (  V16QImode, SImode,    V8SImode);
+  test_vectorize_related_mode (  V16QImode, DImode,    VOIDmode);
+
+  rvv_max_lmul = RVV_M2;
+
+  test_vectorize_related_mode (  V32QImode, QImode,   V32QImode);
+  test_vectorize_related_mode (  V32QImode, HImode,   V32HImode);
+  test_vectorize_related_mode (  V32QImode, SImode,   V16SImode);
+  test_vectorize_related_mode (  V32QImode, DImode,    VOIDmode);
+
+  rvv_max_lmul = RVV_M4;
+
+  test_vectorize_related_mode ( V128QImode, QImode,  V128QImode);
+  test_vectorize_related_mode ( V128QImode, HImode,   V64HImode);
+  test_vectorize_related_mode ( V128QImode, SImode,   V32SImode);
+  test_vectorize_related_mode ( V128QImode, DImode,    VOIDmode);
+
+  rvv_max_lmul = RVV_M8;
+
+  test_vectorize_related_mode ( V128QImode, QImode,  V128QImode);
+  test_vectorize_related_mode ( V128QImode, HImode,  V128HImode);
+  test_vectorize_related_mode ( V128QImode, SImode,   V64SImode);
+  test_vectorize_related_mode ( V128QImode, DImode,    VOIDmode);
+
+  rvv_vector_bits = backup_rvv_vector_bits;
+  rvv_max_lmul = backup_rvv_max_lmul;
+
+}
+
+static void
+run_vectorize_related_mode_vls_selftests (void)
+{
+  run_vectorize_related_mode_vls_rv64gcv_selftests ();
+  run_vectorize_related_mode_vls_rv32gc_zve32x_zvl256b_selftests ();
+}
+
+static void
+run_vectorize_related_mode_selftests (void)
+{
+  run_vectorize_related_mode_vla_selftests ();
+  run_vectorize_related_mode_vls_selftests ();
+}
+
 namespace selftest {
 /* Run all target-specific selftests.  */
 void
@@ -387,6 +543,7 @@ riscv_run_selftests (void)
     run_poly_int_selftests ();
   run_const_vector_selftests ();
   run_broadcast_selftests ();
+  run_vectorize_related_mode_selftests ();
 }
 } // namespace selftest
 #endif /* #if CHECKING_P */
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index b30a95d0e3f..012ca5918cb 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -3064,7 +3064,7 @@ can_find_related_mode_p (machine_mode vector_mode, 
scalar_mode element_mode,
                     GET_MODE_SIZE (element_mode), nunits))
     return true;
   if (riscv_v_ext_vls_mode_p (vector_mode)
-      && multiple_p (TARGET_MIN_VLEN * TARGET_MAX_LMUL,
+      && multiple_p ((TARGET_MIN_VLEN * TARGET_MAX_LMUL) / BITS_PER_UNIT,
                     GET_MODE_SIZE (element_mode), nunits))
     return true;
   return false;
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f-1.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f-1.c
index 66b4dc636d3..4650b5e57ea 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f-1.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f-1.c
@@ -3,4 +3,4 @@
 
 #include "template-1.h"
 
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 2 "vect" 
} } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 3 "vect" 
} } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f_zvl256b-1.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f_zvl256b-1.c
index e50af33f48b..5c253ce70c3 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f_zvl256b-1.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f_zvl256b-1.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-march=rv32gc_zve32f_zvl256b -mabi=ilp32d 
-mrvv-vector-bits=scalable -fdump-tree-vect-details" } */
+/* { dg-options "-march=rv32gc_zve32f_zvl256b -mabi=ilp32d 
-mrvv-vector-bits=scalable -mrvv-max-lmul=m2 -fdump-tree-vect-details" } */
 
 #include "template-1.h"
 
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x_zvl256b-1.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x_zvl256b-1.c
index 889689523c8..77f98acf87e 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x_zvl256b-1.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x_zvl256b-1.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-march=rv32gc_zve32x_zvl256b -mabi=ilp32d 
-mrvv-vector-bits=scalable -fdump-tree-vect-details" } */
+/* { dg-options "-march=rv32gc_zve32x_zvl256b -mabi=ilp32d 
-mrvv-vector-bits=scalable -mrvv-max-lmul=m2 -fdump-tree-vect-details" } */
 
 #include "template-1.h"
 
-- 
2.34.1

Reply via email to