Bug 115562 - RISC-V: ICE because of reused fndecl with target-arch attribute
Summary: RISC-V: ICE because of reused fndecl with target-arch attribute
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 15.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2024-06-20 15:45 UTC by Christoph Müllner
Modified: 2024-07-17 06:33 UTC (History)
0 users

See Also:
Host:
Target: riscv
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Christoph Müllner 2024-06-20 15:45:11 UTC
Minimal (?) reproducer:

$ cat foo-copy.c 
void foo (void);

__attribute__((target("arch=+zbb")))
void*
memcpy (void *d, const void *, unsigned long)
{
  return d;
}
__attribute__((target("arch=+zbb"))) void fun0(void) {}
__attribute__((target("arch=+zbb"))) void fun1(void) {}
__attribute__((target("arch=+zbb"))) void fun2(void) {}
__attribute__((target("arch=+zbb"))) void fun3(void) {}
__attribute__((target("arch=+zbb"))) void fun4(void) {}
__attribute__((target("arch=+zbb"))) void fun5(void) {}
__attribute__((target("arch=+zbb"))) void fun6(void) {}
__attribute__((target("arch=+zbb"))) void fun7(void) {}
__attribute__((target("arch=+zbb"))) void fun8(void) {}
__attribute__((target("arch=+zbb"))) void fun9(void) {}
__attribute__((target("arch=+zbb"))) void fun10(void) {}
__attribute__((target("arch=+zbb"))) void fun11(void) {}
__attribute__((target("arch=+zbb"))) void fun12(void) {}

This is similar to PR115554, but triggers the assertion in riscv_func_target_put()
because when processing `fun12` the fndecl is equal to the previously processed
fndecl of `memcpy`. I.e., the assumption that the fndecl pointer can be used as
an identifier (or comparable for the hash-table) does not hold.

Like PR115554, this bug is part of GCC14 and on the master branch.

The ICE looks the same as for PR115554 (the same assertion is triggered).
To analyze this issue, I've extended riscv_func_target_put() like this:

+  if (*target_info_slot)
+    {
+      inform (loc, "Hash collision detected:");
+      inform (loc, "  old function: %qE (%p)", (*target_info_slot)->fn_decl, (*target_info_slot)->fn_decl);
+      inform (loc, "  old attributes: %s", (*target_info_slot)->fn_target_name.c_str());
+      inform (loc, "  new function: %qE", fn_decl);
+      inform (loc, "  new attributes: %s", fn_target_name.c_str ());
+    }
+  else
+    {
+      inform (loc, "Adding target attributes to function:");
+      inform (loc, "  new function: %qE (%p)", fn_decl, fn_decl);
+      inform (loc, "  new attributes: %s", fn_target_name.c_str ());
+    }
   gcc_assert (!*target_info_slot);

Additionally, I've included tree.h and added "location_t loc" as parameter
of this function. This gives the following output on the reproducer above:

$ /opt/riscv-mainline/bin/riscv64-unknown-linux-gnu-gcc -c foo-copy.c
foo-copy.c:5:1: note: Adding target attributes to function:                                                            
    5 | memcpy (void *d, const void *, unsigned long)                                                                  
      | ^~~~~~                                            
foo-copy.c:5:1: note:   new function: 'memcpy' (0x7f295879e200)  // first appearance
foo-copy.c:5:1: note:   new attributes: rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zaamo1p0_zalrsc1p0_zbb1p0  
foo-copy.c:10:43: note: Adding target attributes to function:
   10 | __attribute__((target("arch=+zbb"))) void fun0(void) {}
      |                                           ^~~~
foo-copy.c:10:43: note:   new function: 'fun0' (0x7f295879e400)
foo-copy.c:10:43: note:   new attributes: rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zaamo1p0_zalrsc1p0_zbb1p0
[...]
foo-copy.c:22:43: note: Adding target attributes to function:
   22 | __attribute__((target("arch=+zbb"))) void fun11(void) {}
      |                                           ^~~~~
foo-copy.c:22:43: note:   new function: 'fun11' (0x7f295879ef00)
foo-copy.c:22:43: note:   new attributes: rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zaamo1p0_zalrsc1p0_zbb1p0
foo-copy.c:23:43: note: Hash collision detected:
   23 | __attribute__((target("arch=+zbb"))) void fun12(void) {}
      |                                           ^~~~~
foo-copy.c:23:43: note:   old function: 'fun12' (0x7f295879e200)  // same address!
foo-copy.c:23:43: note:   old attributes: rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zaamo1p0_zalrsc1p0_zbb1p0
foo-copy.c:23:43: note:   new function: 'fun12'
foo-copy.c:23:43: note:   new attributes: rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zaamo1p0_zalrsc1p0_zbb1p0
foo-copy.c:23:1: internal compiler error: in riscv_func_target_put, at common/config/riscv/riscv-common.cc:536
   23 | __attribute__((target("arch=+zbb"))) void fun12(void) {}
      | ^~~~~~~~~~~~~

As can be seen in the example above, fndecl of `memcpy` has the address
0x7f295879e200, which is equal to the address of fndecl of `fun12`.

Note that even small adjustments to the source will break the reproducer.
Therefore, I could not rename `memcpy` to something different.
Comment 1 Christoph Müllner 2024-06-20 15:55:37 UTC
This issue was discovered while analyzing a build issue with a patchset
to introduce optimized string processing routines for RISC-V in glibc.

See also:
  https://sourceware.org/pipermail/libc-alpha/2024-June/157627.html