https://gcc.gnu.org/g:f6ee4d2a6070fda98a7cbb65aa8b3bb2903d77d0

commit r17-4591-gf6ee4d2a6070fda98a7cbb65aa8b3bb2903d77d0
Author: Tamar Christina <[email protected]>
Date:   Wed Sep 23 07:55:53 2026 +0100

    AArch64: Apply VF cap consistently
    
    Use the same VF cap in the AArch64 body-cost adjustment and in the
    main-loop comparison.
    
    Known fixed-trip loops can execute fewer lanes than the architectural VF.
    The body-cost path already wanted to account for that, but the main-loop
    comparison still used the uncapped VF.  This made the two parts of the
    cost model rank the same loop differently.
    
    This factors the cap into a small helper and uses it in both places.
    
    gcc/ChangeLog:
    
            * config/aarch64/aarch64.cc (aarch64_vect_vf_for_cost): New
            function.
            (aarch64_vector_costs::adjust_body_cost): Use it.
            (aarch64_vector_costs::better_main_loop_than_p): Likewise.

Diff:
---
 gcc/config/aarch64/aarch64.cc | 50 ++++++++++++++++++++++++++-----------------
 1 file changed, 30 insertions(+), 20 deletions(-)

diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index f9d906f449f2..a96c140522c6 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -18986,6 +18986,29 @@ aarch64_external_adjust_stmt_cost (vect_cost_for_stmt 
kind, slp_tree node,
   return stmt_cost;
 }
 
+/* Get the effecive VF to use for the loop in LOOP_VINFO.  This is the VF that
+   should be used for costing purposes only.  */
+static inline unsigned int
+aarch64_vect_vf_for_cost (loop_vec_info loop_vinfo)
+{
+  unsigned int estimated_vf = vect_vf_for_cost (loop_vinfo);
+
+  /* If we know we have a single partial vector iteration, cap the VF
+     to the number of scalar iterations for costing purposes.  */
+  if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo))
+    {
+      auto niters = LOOP_VINFO_INT_NITERS (loop_vinfo);
+      if (niters < estimated_vf && dump_enabled_p ())
+       dump_printf_loc (MSG_NOTE, vect_location,
+                        "Scalar loop iterates at most %wd times.  Capping VF "
+                        " from %d to %wd\n", niters, estimated_vf, niters);
+
+      estimated_vf = MIN (estimated_vf, niters);
+    }
+
+  return estimated_vf;
+}
+
 unsigned
 aarch64_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind,
                                     stmt_vec_info stmt_info, slp_tree node,
@@ -19349,7 +19372,7 @@ adjust_body_cost (loop_vec_info loop_vinfo,
 
   const auto &scalar_ops = scalar_costs->m_ops[0];
   const auto &vector_ops = m_ops[0];
-  unsigned int estimated_vf = vect_vf_for_cost (loop_vinfo);
+  unsigned int estimated_vf = aarch64_vect_vf_for_cost (loop_vinfo);
   unsigned int orig_body_cost = body_cost;
   bool should_disparage = false;
 
@@ -19357,19 +19380,6 @@ adjust_body_cost (loop_vec_info loop_vinfo,
     dump_printf_loc (MSG_NOTE, vect_location,
                     "Original vector body cost = %d\n", body_cost);
 
-  /* If we know we have a single partial vector iteration, cap the VF
-     to the number of scalar iterations for costing purposes.  */
-  if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo))
-    {
-      auto niters = LOOP_VINFO_INT_NITERS (loop_vinfo);
-      if (niters < estimated_vf && dump_enabled_p ())
-       dump_printf_loc (MSG_NOTE, vect_location,
-                        "Scalar loop iterates at most %wd times.  Capping VF "
-                        " from %d to %wd\n", niters, estimated_vf, niters);
-
-      estimated_vf = MIN (estimated_vf, niters);
-    }
-
   fractional_cost scalar_cycles_per_iter
     = scalar_ops.min_cycles_per_iter () * estimated_vf;
 
@@ -19561,14 +19571,16 @@ better_main_loop_than_p (const vector_costs 
*uncast_other) const
 
   auto this_loop_vinfo = as_a<loop_vec_info> (this->m_vinfo);
   auto other_loop_vinfo = as_a<loop_vec_info> (other->m_vinfo);
+  auto this_loop_vf = aarch64_vect_vf_for_cost (this_loop_vinfo);
+  auto other_loop_vf = aarch64_vect_vf_for_cost (other_loop_vinfo);
 
   if (dump_enabled_p ())
     dump_printf_loc (MSG_NOTE, vect_location,
                     "Comparing two main loops (%s at VF %d vs %s at VF %d)\n",
                     GET_MODE_NAME (this_loop_vinfo->vector_mode),
-                    vect_vf_for_cost (this_loop_vinfo),
+                    this_loop_vf,
                     GET_MODE_NAME (other_loop_vinfo->vector_mode),
-                    vect_vf_for_cost (other_loop_vinfo));
+                    other_loop_vf);
 
   /* Apply the unrolling heuristic described above
      m_unrolled_advsimd_niters.  */
@@ -19604,10 +19616,8 @@ better_main_loop_than_p (const vector_costs 
*uncast_other) const
          other->m_ops[i].dump ();
        }
 
-      auto this_estimated_vf = (vect_vf_for_cost (this_loop_vinfo)
-                               * this->m_ops[i].vf_factor ());
-      auto other_estimated_vf = (vect_vf_for_cost (other_loop_vinfo)
-                                * other->m_ops[i].vf_factor ());
+      auto this_estimated_vf = (this_loop_vf * this->m_ops[i].vf_factor ());
+      auto other_estimated_vf = (other_loop_vf * other->m_ops[i].vf_factor ());
 
       /* If it appears that one loop could process the same amount of data
         in fewer cycles, prefer that loop over the other one.  */

Reply via email to