https://gcc.gnu.org/g:6fea108d4725f1aa79ce3acd9b6933da003d11a4

commit r17-4176-g6fea108d4725f1aa79ce3acd9b6933da003d11a4
Author: Robin Dapp <[email protected]>
Date:   Fri Sep 11 16:59:27 2026 +0200

    expmed: Use store_bit_field for unsplittable target. [PR127323]
    
    In extract_integral_bit_field we can get an unsplittable target like
    (reg:V2DF) and we try to store word-sized parts into it.  After the
    regmode-natural-size changes, this will ICE.  This patch goes through
    store_bit_field if we cannot use a subreg.  For riscv, this will
    currently cause one spill per iteration but that can be mitigated later.
    
    gcc/ChangeLog:
    
            PR middle-end/127323
    
            * expmed.cc (extract_integral_bit_field): Use store_bit_field if
            operand_subword fails.
    
    gcc/testsuite/ChangeLog:
    
            * g++.target/riscv/rvv/autovec/pr127323.C: New test.

Diff:
---
 gcc/expmed.cc                                      |  6 ++--
 .../g++.target/riscv/rvv/autovec/pr127323.C        | 39 ++++++++++++++++++++++
 2 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/gcc/expmed.cc b/gcc/expmed.cc
index 13803c6bbd04..c6494484251f 100644
--- a/gcc/expmed.cc
+++ b/gcc/expmed.cc
@@ -2022,14 +2022,16 @@ extract_integral_bit_field (rtx op0, 
opt_scalar_int_mode op0_mode,
                                   (unsignedp ? 1 : -1), target_part,
                                   mode, word_mode, reverse, fallback_p, NULL);
 
-         gcc_assert (target_part);
          if (!result_part)
            {
              delete_insns_since (last);
              return NULL;
            }
 
-         if (result_part != target_part)
+         if (!target_part)
+           store_bit_field (target, BITS_PER_WORD, i * BITS_PER_WORD,
+                            0, 0, word_mode, result_part, false, i == 0);
+         else if (result_part != target_part)
            emit_move_insn (target_part, result_part);
        }
 
diff --git a/gcc/testsuite/g++.target/riscv/rvv/autovec/pr127323.C 
b/gcc/testsuite/g++.target/riscv/rvv/autovec/pr127323.C
new file mode 100644
index 000000000000..86141b749368
--- /dev/null
+++ b/gcc/testsuite/g++.target/riscv/rvv/autovec/pr127323.C
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mrvv-max-lmul=conv-dynamic -march=rv64gcv -mabi=lp64d 
-mtune=generic-ooo" } */
+
+typedef double VECTOR[3];
+enum { X, Y, Z };
+struct Bicubic_Patch_Struct {
+  VECTOR Control_Points[4][4];
+  VECTOR Bounding_Sphere_Center;
+  double Bounding_Sphere_Radius;
+};
+void Assign_Vector(VECTOR d, VECTOR s) {
+  d[X] = s[X];
+  d[Y] = s[Y];
+  d[Z] = s[Z];
+}
+typedef struct Bicubic_Patch_Struct BICUBIC_PATCH;
+namespace std {
+void find_average(int vector_count, VECTOR *vectors, VECTOR, double *radius) {
+  int i;
+  double r0, r1, yc, zc, y0;
+  for (i = 0; i < vector_count; i++) {
+    yc += vectors[i][Y];
+    zc += vectors[i][Z];
+  }
+  y0 = yc - zc;
+  r1 = y0;
+  if (r1)
+    *radius = r0;
+}
+void Precompute_Patch_Values(BICUBIC_PATCH *Shape) {
+  int i, j;
+  VECTOR Control_Points[6];
+  for (i = 0; i < 4; i++)
+    for (j = 0; j < 4; j++)
+      Assign_Vector(Control_Points[4 * i + j], Shape->Control_Points[i][j]);
+  find_average(6, Control_Points, Shape->Bounding_Sphere_Center,
+               &Shape->Bounding_Sphere_Radius);
+}
+}

Reply via email to