5 Commits

Author SHA1 Message Date
Joseph Huber
3590945a11 [AMDGPU] Add attribute to AMDGPU ctor / dtor to indicate single threadedness
We only expect these ctor / dtor functions to be called with a single
thread. Add the appropriate attributes to indicate this to the backend.

Reviewed By: arsenm

Differential Revision: https://reviews.llvm.org/D151153
2023-05-24 07:24:17 -05:00
Joseph Huber
8b132747cd [AMDGPU] Rewrite device ctor / dtor handling to use .init / .fini sections
Currently, AMDGPU has special handling for constructors and destructors.
We manuall emit a kernel that calls the functoins listed in the global
constructor / destructor list. This currently has two main problems. The
first is that we do not repsect the priortiy and simply call them in any
order. The second is that we redefine the symbol unconditionally which
coulid have a different definition, meaning we cannot merge any code
with a constructor post-codegen. This patch changes the handling to
instead use the standard support for travering the `.init_array` and
`.fini_array` sections the compiler creates. This allows us to emit a
single kernel with `odr` semantics, so even if we emit this multiple
times they will be merged into a single kernel.

Reviewed By: arsenm

Differential Revision: https://reviews.llvm.org/D150675
2023-05-19 16:22:01 -05:00
Joseph Huber
a1da746157 [AMDGPU] Place global constructors in .init_array and .fini_array
For the GPU, we emit external kernels that call the initializers and
constructors, however if we had a persistent kernel like in the `_start`
kernel for the `libc` project, we could initialize the standard way of
calling constructors. This patch adds new global variables containing
pointers to the constructors to be called. If these are placed in the
`.init_array` and `.fini_array` sections, then the backend will handle
them specially. The linker will then provide the `__init_array_` and
`__fini_array_` sections to traverse them. An implementation would look
like this.

```
extern uintptr_t __init_array_start[];
extern uintptr_t __init_array_end[];
extern uintptr_t __fini_array_start[];
extern uintptr_t __fini_array_end[];

using InitCallback = void(int, char **, char **);
using FiniCallback = void(void);

extern "C" [[gnu::visibility("protected"), clang::amdgpu_kernel]] void
_start(int argc, char **argv, char **envp) {
  uint64_t init_array_size = __init_array_end - __init_array_start;
  for (uint64_t i = 0; i < init_array_size; ++i)
    reinterpret_cast<InitCallback *>(__init_array_start[i])(argc, argv, env);
  uint64_t fini_array_size = __fini_array_end - __fini_array_start;
  for (uint64_t i = 0; i < fini_array_size; ++i)
    reinterpret_cast<FiniCallback *>(__fini_array_start[i])();
}
```

Reviewed By: yaxunl

Differential Revision: https://reviews.llvm.org/D149340
2023-04-29 08:40:19 -05:00
Matt Arsenault
9cc0779c4e AMDGPU: Erase llvm.global_ctors/global_dtors after lowering
We should be able to run the pass multiple times without breaking
anything. If we still need to track these for some reason, we could
replace with new entries for the kernels.
2022-12-09 14:25:32 -05:00
Matt Arsenault
41c96e9483 AMDGPU: Fix not emitting code for exotic constructor types
This was simply ignoring any entries that weren't direct function
calls. This really should have been erroring on anything
unexpected. We should be able to handle calling just about anything
these days, so just call anything.
2022-12-09 13:22:12 -05:00