https://gcc.gnu.org/g:8c7c10e82d661785181f199fdc6b24890b30a54e
commit r17-4161-g8c7c10e82d661785181f199fdc6b24890b30a54e Author: Richard Biener <[email protected]> Date: Fri Sep 11 10:31:58 2026 +0200 tree-optimization/127310 - ICE with lane-reducing reduction The following fixes an issue with wrong loop mask registering due to the costing code adjusting ncopies_for_cost before we use it for mask registering. PR tree-optimization/127310 * tree-vect-loop.cc (vectorizable_lane_reducing): Apply costing after registering loop masks. * gcc.dg/vect/vect-pr127310.c: New testcase. Diff: --- gcc/testsuite/gcc.dg/vect/vect-pr127310.c | 29 +++++++++++++++++++++++ gcc/tree-vect-loop.cc | 38 +++++++++++++++---------------- 2 files changed, 48 insertions(+), 19 deletions(-) diff --git a/gcc/testsuite/gcc.dg/vect/vect-pr127310.c b/gcc/testsuite/gcc.dg/vect/vect-pr127310.c new file mode 100644 index 000000000000..815b631c0659 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-pr127310.c @@ -0,0 +1,29 @@ +/* { dg-additional-options "-march=armv8-a+sve" { target aarch64_sve_hw } } */ + +#include "tree-vect.h" + +__attribute__ ((noipa)) unsigned int +mixed_dot_induction (unsigned int n) +{ + unsigned int sum = 0; + for (unsigned int i = 0; i < n; ++i) + sum += (signed char) i * (unsigned char) (i * 17 + 3); + return sum; +} + +int +main () +{ + unsigned int expected = 0; + check_vect (); +#pragma GCC novector + for (unsigned int n = 0; n <= 1025; ++n) + { + if (mixed_dot_induction (n) != expected) + __builtin_abort (); + int x = (int) (n & 127) - (int) (n & 128); + int y = (n * 17 + 3) & 255; + expected += x * y; + } + return 0; +} diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc index 19e7a6fa884f..4a0492381422 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -6866,25 +6866,6 @@ vectorizable_lane_reducing (loop_vec_info loop_vinfo, stmt_vec_info stmt_info, } gcc_assert (ncopies_for_cost >= 1); - if (vect_is_emulated_mixed_dot_prod (slp_node)) - { - /* We need extra two invariants: one that contains the minimum signed - value and one that contains half of its negative. */ - int prologue_stmts = 2; - unsigned cost = record_stmt_cost (cost_vec, prologue_stmts, - scalar_to_vec, slp_node, 0, - vect_prologue); - if (dump_enabled_p ()) - dump_printf (MSG_NOTE, "vectorizable_lane_reducing: " - "extra prologue_cost = %d .\n", cost); - - /* Three dot-products and a subtraction. */ - ncopies_for_cost *= 4; - } - - record_stmt_cost (cost_vec, (int) ncopies_for_cost, vector_stmt, slp_node, - 0, vect_body); - if (LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo)) { enum tree_code code = gimple_assign_rhs_code (stmt); @@ -6905,6 +6886,25 @@ vectorizable_lane_reducing (loop_vec_info loop_vinfo, stmt_vec_info stmt_info, } } + if (vect_is_emulated_mixed_dot_prod (slp_node)) + { + /* We need extra two invariants: one that contains the minimum signed + value and one that contains half of its negative. */ + int prologue_stmts = 2; + unsigned cost = record_stmt_cost (cost_vec, prologue_stmts, + scalar_to_vec, slp_node, 0, + vect_prologue); + if (dump_enabled_p ()) + dump_printf (MSG_NOTE, "vectorizable_lane_reducing: " + "extra prologue_cost = %d .\n", cost); + + /* Three dot-products and a subtraction. */ + ncopies_for_cost *= 4; + } + + record_stmt_cost (cost_vec, (int) ncopies_for_cost, vector_stmt, slp_node, + 0, vect_body); + /* Transform via vect_transform_reduction. */ SLP_TREE_TYPE (slp_node) = reduc_vec_info_type; return true;
