https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127245
Bug ID: 127245
Summary: [17 Regression] ICE in vect_create_constant_vectors at
tree-vect-slp.cc:10944 since r17-3968
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Keywords: ice-on-valid-code
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: dhruvc at gcc dot gnu.org
CC: rguenth at gcc dot gnu.org
Target Milestone: ---
Target: aarch64
Showing up in SPEC2026 LLVM again.
Min repro (gcc.dg/vect/vect-pr127195.c):
===
typedef struct {
unsigned bold : 1;
unsigned : 16;
} vbi_char;
typedef struct {
vbi_char text[];
} vbi_page;
vbi_page enhance_pg;
vbi_char *enhance_acp = &enhance_pg.text[1];
int enhance_col, enhance_column;
void enhance()
{
for (;;) {
int bold;
enhance_col = enhance_column;
for (; enhance_col; enhance_col++)
enhance_acp[enhance_col].bold = bold;
}
}
===
Flags: -O2 -march=armv8-a+sve
Compiler explorer: https://godbolt.org/z/9d9Y1bPTG
===
LLM-generated explanation:
d8f1bd8c added an is_constant requirement to vect_get_num_copies_for_invariant:
if (can_div_away_from_zero_p (vf, TYPE_VECTOR_SUBPARTS (vectype), nvectors)
&& (TYPE_VECTOR_SUBPARTS (vectype) * *nvectors - vf).is_constant (&rem))
{
*excess_elts = rem;
return true;
}
return false;
Code generation asserts on that predicate for the invariant child node
(tree-vect-slp.cc:10944):
bool res = vect_get_num_copies_for_invariant (vinfo, op_node,
&number_of_vectors,
&excess_elts);
gcc_assert (res);
But the analysis-time guard in vect_slp_analyze_node_operations
(tree-vect-slp.cc:9130) queries the parent instead:
tree vector_type = SLP_TREE_VECTYPE (child); /* read off the child ... */
...
/* Make sure we can generate them and then cost them. */
unsigned nvectors, excess_elts;
if (!vect_get_num_copies_for_invariant (vinfo, node, &nvectors, &excess_elts))
return false; /* ... but queried on NODE
*/
vect_prologue_cost_for_slp (child, nvectors, cost_vec); /* ... and costed on
the child */
When parent and child carry different vector types, the guard passes on the
parent and code generation then aborts on the child. gdb on trunk 301afaab with
the reduced test below:
CODEGEN op_node = 0x382c590, lanes 1, vect_external_def
vectype = vector([16,16]) unsigned char
VF = [4,4]
nvectors = 1
[16,16] * 1 - [4,4] = [12,12] -> not constant -> res = false ->
assert fires
ANALYSIS the same child 0x382c590 ALREADY has vectype vector([16,16]) unsigned
char,
but the predicate was queried with the parent, vector([4,4]) unsigned
int,
for which [4,4] * 1 - [4,4] = 0 is constant -> guard passes
The parent is _27 = (unsigned int) _6; the child is the external one-lane node
holding _6, which is a 1-bit bitfield, so its vector type is unsigned-char
based and has 4x as many subparts as the parent's.
The wrong-node query is older than the culprit (it came in with bb1344be44e,
2026-08-19), but it was harmless: before d8f1bd8c the predicate only did
can_div_away_from_zero_p, which succeeds here. d8f1bd8c is what turned a latent
mismatch into an ICE.