Hi,

this is a bit of a follow up of the latest expmed change.

In extract_bit_field_1 we try to get a better vector mode before
extracting from it.  Better refers to the case when the requested target
mode does not equal the inner mode of the vector to extract from and we
have an equivalent tieable vector mode with a fitting inner mode.

On riscv this triggered an ICE (PR112999) because we would take the
detour of extracting from a mask-mode vector via a vector integer mode.
One element of that mode could be subreg-punned with TImode which, in
turn, would need to be operated on in DImode chunks.

As the backend might return the extracted value in a different mode than
the inner mode of the input vector, we might already have a mode
equivalent to the target mode.  Therefore, this patch first obtains the
mode the backend uses for the particular vec_extract and then compares
it against the target mode.  Only if those disagree we try to find a
better mode.  Otherwise we continue with the initial one.

Bootstrapped and regtested on x86, aarch64 and power10.  Regtested
on riscv.

Regards
 Robin

gcc/ChangeLog:

        PR target/112999

        * expmed.cc (extract_bit_field_1):  Get vec_extract's result
        element mode from insn_data and compare it to the target mode.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/rvv/autovec/pr112999.c: New test.
---
 gcc/expmed.cc                                   | 17 +++++++++++++++--
 .../gcc.target/riscv/rvv/autovec/pr112999.c     | 17 +++++++++++++++++
 2 files changed, 32 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112999.c

diff --git a/gcc/expmed.cc b/gcc/expmed.cc
index ed17850ff74..6fbe4d9cfaf 100644
--- a/gcc/expmed.cc
+++ b/gcc/expmed.cc
@@ -1722,10 +1722,23 @@ extract_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, 
poly_uint64 bitnum,
        }
     }
 
+  /* The target may prefer to return the extracted value in a different mode
+     than INNERMODE.  */
+  machine_mode outermode = GET_MODE (op0);
+  machine_mode element_mode = GET_MODE_INNER (outermode);
+  if (VECTOR_MODE_P (outermode) && !MEM_P (op0))
+    {
+      enum insn_code icode
+       = convert_optab_handler (vec_extract_optab, outermode, element_mode);
+
+      if (icode != CODE_FOR_nothing)
+       element_mode = insn_data[icode].operand[0].mode;
+    }
+
   /* See if we can get a better vector mode before extracting.  */
   if (VECTOR_MODE_P (GET_MODE (op0))
       && !MEM_P (op0)
-      && GET_MODE_INNER (GET_MODE (op0)) != tmode)
+      && element_mode != tmode)
     {
       machine_mode new_mode;
 
@@ -1755,7 +1768,7 @@ extract_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, 
poly_uint64 bitnum,
   /* Use vec_extract patterns for extracting parts of vectors whenever
      available.  If that fails, see whether the current modes and bitregion
      give a natural subreg.  */
-  machine_mode outermode = GET_MODE (op0);
+  outermode = GET_MODE (op0);
   if (VECTOR_MODE_P (outermode) && !MEM_P (op0))
     {
       scalar_mode innermode = GET_MODE_INNER (outermode);
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112999.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112999.c
new file mode 100644
index 00000000000..c049c5a0386
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112999.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl512b -mabi=lp64d 
--param=riscv-autovec-lmul=m8 --param=riscv-autovec-preference=fixed-vlmax -O3 
-fno-vect-cost-model -fno-tree-loop-distribute-patterns" } */
+
+int a[1024];
+int b[1024];
+
+_Bool
+fn1 ()
+{
+  _Bool tem;
+  for (int i = 0; i < 1024; ++i)
+    {
+      tem = !a[i];
+      b[i] = tem;
+    }
+  return tem;
+}
-- 
2.43.0

Reply via email to