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.

Reply via email to