i386: Fix ICE with target_clones inlining

When a target_clones function is inlined, the resolver function's
assembler name must be properly registered in the symbol table.
Using SET_DECL_ASSEMBLER_NAME only updates the tree node without
notifying the symbol table, which can lead to an ICE during IPA
inlining when the assembler name hash becomes inconsistent.

Replace SET_DECL_ASSEMBLER_NAME with symtab->change_decl_assembler_name
in make_resolver_func to properly update the symbol table's assembler
name mapping.

This only happens on x86, other targets already uses
symtab->change_decl_assembler_name.

Fixes: b500cd2634 ("x86: fmv: Refactor FMV name mangling.")

gcc/ChangeLog:

	* config/i386/i386-features.cc (make_resolver_func): Use
	symtab->change_decl_assembler_name instead of
	SET_DECL_ASSEMBLER_NAME to properly update the symbol table.

gcc/testsuite/ChangeLog:

	* gcc.target/i386/tct-ipa-inline-ice.c: New test.

Signed-off-by: Yangyu Chen <cyy@cyyself.name>
This commit is contained in:
Yangyu Chen
2026-03-02 15:09:05 +08:00
committed by Uros Bizjak
parent 63fef6d337
commit e769ec31ee
2 changed files with 49 additions and 1 deletions

View File

@@ -5629,7 +5629,7 @@ make_resolver_func (const tree default_decl,
tree id = ix86_mangle_decl_assembler_name
(decl, node->function_version ()->assembler_name);
SET_DECL_ASSEMBLER_NAME (decl, id);
symtab->change_decl_assembler_name (decl, id);
DECL_NAME (decl) = DECL_NAME (default_decl);
TREE_USED (decl) = 1;

View File

@@ -0,0 +1,48 @@
/* Test function multiversioning and inlining of a function with a
target_clones attribute. Note, we need to allow inlining of
target_clones functions, see
"Do not inline functions with multiple clone targets." in c-attribs.cc,
otherwise the test would not trigger the ICE. */
/* { dg-do assemble } */
/* { dg-require-ifunc "" } */
/* { dg-options "-O3" } */
struct range_state
{
unsigned int n;
unsigned int s[58];
unsigned int *q[58];
};
struct coder_state
{
struct range_state r;
unsigned int t;
unsigned int x[12];
};
inline void
bar(struct range_state *r, unsigned int *ptr, unsigned int value)
{
r->s[r->n] = value;
r->q[r->n] = ptr;
++r->n;
}
__attribute__((target_clones("default", "arch=x86-64-v2")))
inline void
foo(struct coder_state *c, unsigned int back)
{
if (back == ~0u) {
bar(&c->r, &c->x[c->t], 0);
}
}
__attribute__((target_clones("default", "arch=x86-64-v2")))
int
ice_trigger(struct coder_state *c, unsigned int back)
{
while (1) {
foo(c, back);
}
}