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.")
Signed-off-by: Yangyu Chen <[email protected]>
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.
---
To reproduce the ICE in the test, we need to allow inlining of
target_clones functions, just apply the following patch to c-attribs.cc:
diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index 10d9a51418e..8428e303f08 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -6439,9 +6439,6 @@ handle_target_clones_attribute (tree *node, tree name,
tree ARG_UNUSED (args),
"single %<target_clones%> attribute is ignored");
*no_add_attrs = true;
}
- else
- /* Do not inline functions with multiple clone targets. */
- DECL_UNINLINABLE (*node) = 1;
}
else
{
---
gcc/config/i386/i386-features.cc | 2 +-
.../gcc.target/i386/tct-ipa-inline-ice.c | 48 +++++++++++++++++++
2 files changed, 49 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.target/i386/tct-ipa-inline-ice.c
diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc
index 0e4fdcd2853..9200e0c076c 100644
--- a/gcc/config/i386/i386-features.cc
+++ b/gcc/config/i386/i386-features.cc
@@ -5601,7 +5601,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;
diff --git a/gcc/testsuite/gcc.target/i386/tct-ipa-inline-ice.c
b/gcc/testsuite/gcc.target/i386/tct-ipa-inline-ice.c
new file mode 100644
index 00000000000..b8f77372e00
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/tct-ipa-inline-ice.c
@@ -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);
+ }
+}
--
2.47.3