https://gcc.gnu.org/g:7d351b07e5b85c518b5cbe06a6a57cb653911195

commit r17-1655-g7d351b07e5b85c518b5cbe06a6a57cb653911195
Author: Richard Biener <[email protected]>
Date:   Wed Jun 17 13:19:56 2026 +0200

    Add vec_deconstruct costing kind
    
    The following adds vec_decostruct to replace nunits * vec_to_scalar
    which allows for more precise costing whenever vectorization
    needs to decompose a vector to pieces, like for emulated gather/scatter
    but also for strided [SLP] loads/stores.
    
    This requires changes across targets, both for the different kind
    but also for the difference in expected count.  For now this adjusts
    them all to handle vec_deconstruct like vec_construct to avoid ICEing.
    
            * target.h (vect_cost_for_stmt::vec_deconstruct): New kind.
            * tree-vect-loop.cc (vect_model_reduction_cost): Use it.
            * tree-vect-stmts.cc (vectorizable_store): Likewise.
            (vectorizable_load): Likewise.
            * tree-vectorizer.cc (dump_stmt_cost): Handle vec_deconstruct.
            * config/aarch64/aarch64.cc (aarch64_builtin_vectorization_cost):
            Handle vec_deconstruct like vec_construct.
            * config/i386/i386.cc (ix86_default_vector_cost): Likewise.
            * config/arm/arm.cc (arm_builtin_vectorization_cost): Likewise.
            * config/loongarch/loongarch.cc 
(loongarch_builtin_vectorization_cost):
            Likewise.
            * config/riscv/riscv.cc (riscv_builtin_vectorization_cost):
            Likewise.
            * config/rs6000/rs6000.cc (rs6000_builtin_vectorization_cost):
            Likewise.
            * config/s390/s390.cc (s390_builtin_vectorization_cost): Likewise.
            * targhooks.cc (default_builtin_vectorization_cost): Likewise.

Diff:
---
 gcc/config/aarch64/aarch64.cc     |  1 +
 gcc/config/arm/arm.cc             |  1 +
 gcc/config/i386/i386.cc           |  1 +
 gcc/config/loongarch/loongarch.cc |  1 +
 gcc/config/riscv/riscv.cc         |  1 +
 gcc/config/rs6000/rs6000.cc       |  1 +
 gcc/config/s390/s390.cc           |  1 +
 gcc/target.h                      |  3 ++-
 gcc/targhooks.cc                  |  1 +
 gcc/tree-vect-loop.cc             | 11 +++++------
 gcc/tree-vect-stmts.cc            | 15 +++++++--------
 gcc/tree-vectorizer.cc            |  3 +++
 12 files changed, 25 insertions(+), 15 deletions(-)

diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 42e56512c616..c9403ed94e76 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -17766,6 +17766,7 @@ aarch64_builtin_vectorization_cost (enum 
vect_cost_for_stmt type_of_cost,
                  : simd_costs->int_stmt_cost;
 
       case vec_construct:
+      case vec_deconstruct:
        elements = estimated_poly_value (TYPE_VECTOR_SUBPARTS (vectype));
        return elements / 2 + 1;
 
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index d24b06a64458..0bc66abe238b 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -12732,6 +12732,7 @@ arm_builtin_vectorization_cost (enum vect_cost_for_stmt 
type_of_cost,
         return current_tune->vec_costs->vec_stmt_cost;
 
       case vec_construct:
+      case vec_deconstruct:
        elements = TYPE_VECTOR_SUBPARTS (vectype);
        return elements / 2 + 1;
 
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index b1fd86c2b320..1734996c68a7 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -25699,6 +25699,7 @@ ix86_default_vector_cost (enum vect_cost_for_stmt 
type_of_cost,
         return ix86_vec_cost (mode, ix86_cost->sse_op);
 
       case vec_construct:
+      case vec_deconstruct:
        {
          int n = GET_MODE_NUNITS (mode);
          /* N - 1 element inserts into an SSE vector, the possible
diff --git a/gcc/config/loongarch/loongarch.cc 
b/gcc/config/loongarch/loongarch.cc
index 401119715012..131f7b3f57b6 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -4547,6 +4547,7 @@ loongarch_builtin_vectorization_cost (enum 
vect_cost_for_stmt type_of_cost,
        return 2;
 
       case vec_construct:
+      case vec_deconstruct:
        elements = TYPE_VECTOR_SUBPARTS (vectype);
        if (LASX_SUPPORTED_MODE_P (mode) && !LSX_SUPPORTED_MODE_P (mode))
          return elements / 2 + 3;
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 3be5606ba015..29d9aaf1ffde 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -14065,6 +14065,7 @@ riscv_builtin_vectorization_cost (enum 
vect_cost_for_stmt type_of_cost,
       return fp ? common_costs->fp_stmt_cost : common_costs->int_stmt_cost;
 
     case vec_construct:
+    case vec_deconstruct:
        {
          /* TODO: This is too pessimistic in case we can splat.  */
          int regmove_cost = fp ? get_fr2vr_cost () : get_gr2vr_cost ();
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index 5562d612b22f..afe5d45c1259 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -5113,6 +5113,7 @@ rs6000_builtin_vectorization_cost (enum 
vect_cost_for_stmt type_of_cost,
        return 2;
 
       case vec_construct:
+      case vec_deconstruct:
        /* This is a rough approximation assuming non-constant elements
           constructed into a vector via element insertion.  FIXME:
           vec_construct is not granular enough for uniformly good
diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
index bd2adf6bfa19..1bddd5e454ae 100644
--- a/gcc/config/s390/s390.cc
+++ b/gcc/config/s390/s390.cc
@@ -4385,6 +4385,7 @@ s390_builtin_vectorization_cost (enum vect_cost_for_stmt 
type_of_cost,
        return 3;
 
       case vec_construct:
+      case vec_deconstruct:
        return TYPE_VECTOR_SUBPARTS (vectype) - 1;
 
       default:
diff --git a/gcc/target.h b/gcc/target.h
index 68ba626da6aa..67b04f90f45c 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -212,7 +212,8 @@ enum vect_cost_for_stmt
   cond_branch_taken,
   vec_perm,
   vec_promote_demote,
-  vec_construct
+  vec_construct,
+  vec_deconstruct
 };
 
 /* Separate locations for which the vectorizer cost model should
diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc
index 670bc7aa22cd..113d8836beae 100644
--- a/gcc/targhooks.cc
+++ b/gcc/targhooks.cc
@@ -777,6 +777,7 @@ default_builtin_vectorization_cost (enum vect_cost_for_stmt 
type_of_cost,
         return 3;
 
       case vec_construct:
+      case vec_deconstruct:
        return estimated_poly_value (TYPE_VECTOR_SUBPARTS (vectype)) - 1;
 
       default:
diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
index 4d9b691c3299..0167d52b28b2 100644
--- a/gcc/tree-vect-loop.cc
+++ b/gcc/tree-vect-loop.cc
@@ -4752,10 +4752,10 @@ vect_model_reduction_cost (loop_vec_info loop_vinfo,
                                        node, 0, vect_body);
       else
        {
-         /* Use NELEMENTS extracts and NELEMENTS scalar ops.  */
+         /* Use NCOPIES deconstructs and NELEMENTS scalar ops.  */
          unsigned int nelements = ncopies * vect_nunits_for_cost (vectype);
-         inside_cost = record_stmt_cost (cost_vec, nelements,
-                                         vec_to_scalar, node, 0,
+         inside_cost = record_stmt_cost (cost_vec, ncopies,
+                                         vec_deconstruct, node, 0,
                                          vect_body);
          inside_cost += record_stmt_cost (cost_vec, nelements,
                                           scalar_stmt, node, 0,
@@ -4817,9 +4817,8 @@ vect_model_reduction_cost (loop_vec_info loop_vinfo,
        {
          unsigned estimated_nunits = vect_nunits_for_cost (vectype);
          /* Extraction of scalar elements.  */
-         epilogue_cost += record_stmt_cost (cost_vec,
-                                            2 * estimated_nunits,
-                                            vec_to_scalar, node, 0,
+         epilogue_cost += record_stmt_cost (cost_vec, 2,
+                                            vec_deconstruct, node, 0,
                                             vect_epilogue);
          /* Scalar max reductions via COND_EXPR / MAX_EXPR.  */
          epilogue_cost += record_stmt_cost (cost_vec,
diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc
index 4e7b45f5a6c8..e991e8615253 100644
--- a/gcc/tree-vect-stmts.cc
+++ b/gcc/tree-vect-stmts.cc
@@ -8654,12 +8654,12 @@ vectorizable_store (vec_info *vinfo,
                inside_cost
                  += record_stmt_cost (cost_vec, n_adjacent_stores,
                                       scalar_store, slp_node, 0, vect_body);
-             /* Only need vector extracting when there are more
-                than one stores.  */
+             /* Only need vector deconstruction when there is more
+                than one store.  */
              if (nstores > 1)
                inside_cost
-                 += record_stmt_cost (cost_vec, n_adjacent_stores,
-                                      vec_to_scalar, slp_node, 0, vect_body);
+                 += record_stmt_cost (cost_vec, ncopies,
+                                      vec_deconstruct, slp_node, 0, vect_body);
            }
          if (dump_enabled_p ())
            dump_printf_loc (MSG_NOTE, vect_location,
@@ -9222,11 +9222,11 @@ vectorizable_store (vec_info *vinfo,
                     (we assume the scalar scaling and ptr + offset add is
                     consumed by the load).  */
                  inside_cost
-                   += record_stmt_cost (cost_vec, cnunits, vec_to_scalar,
+                   += record_stmt_cost (cost_vec, 1, vec_deconstruct,
                                         slp_node, 0, vect_body);
                  /* N scalar stores plus extracting the elements.  */
                  inside_cost
-                   += record_stmt_cost (cost_vec, cnunits, vec_to_scalar,
+                   += record_stmt_cost (cost_vec, 1, vec_deconstruct,
                                         slp_node, 0, vect_body);
                  inside_cost
                    += record_stmt_cost (cost_vec, cnunits, scalar_store,
@@ -11201,8 +11201,7 @@ vectorizable_load (vec_info *vinfo,
                {
                  /* For emulated gathers N offset vector element
                     offset add is consumed by the load).  */
-                 inside_cost = record_stmt_cost (cost_vec, const_nunits,
-                                                 vec_to_scalar,
+                 inside_cost = record_stmt_cost (cost_vec, 1, vec_deconstruct,
                                                  slp_node, 0, vect_body);
                  /* N scalar loads plus gathering them into a
                     vector.  */
diff --git a/gcc/tree-vectorizer.cc b/gcc/tree-vectorizer.cc
index ab455c083498..8c824e4ee33a 100644
--- a/gcc/tree-vectorizer.cc
+++ b/gcc/tree-vectorizer.cc
@@ -169,6 +169,9 @@ dump_stmt_cost (FILE *f, int count, enum vect_cost_for_stmt 
kind,
     case vec_construct:
       ks = "vec_construct";
       break;
+    case vec_deconstruct:
+      ks = "vec_deconstruct";
+      break;
     }
   fprintf (f, "%s ", ks);
   if (kind == unaligned_load || kind == unaligned_store)

Reply via email to