Commit Graph

44 Commits

Author SHA1 Message Date
Joseph Huber
d3aabeb7b5 [libc] Treat the locks array as a bitfield
Currently we keep an internal buffer of device memory that is used to
indicate ownership of a port. Since we only use this as a single bit we
can simply turn this into a bitfield. I did this manually rather than
having a separate type as we need very special handling of the masks
used to interact with the locks.

Reviewed By: JonChesterfield

Differential Revision: https://reviews.llvm.org/D155511
2023-07-21 10:49:11 -05:00
Joseph Huber
979fb95021 Revert "[libc] Treat the locks array as a bitfield"
Summary:
This caused test failures on the gfx90a buildbot. This works on my
gfx1030 and the Nvidia buildbots, so we'll need to investigate what is
going wrong here. For now revert it to get the bots green.

This reverts commit 05abcc5792.
2023-07-19 09:27:08 -05:00
Guillaume Chatelet
1f5783474f [libc][NFC] Rename files
This patch mostly renames files so it better reflects the function they declare.

Reviewed By: michaelrj

Differential Revision: https://reviews.llvm.org/D155607
2023-07-19 09:06:29 +00:00
Joseph Huber
05abcc5792 [libc] Treat the locks array as a bitfield
Currently we keep an internal buffer of device memory that is used to
indicate ownership of a port. Since we only use this as a single bit we
can simply turn this into a bitfield. I did this manually rather than
having a separate type as we need very special handling of the masks
used to interact with the locks.

Reviewed By: JonChesterfield

Differential Revision: https://reviews.llvm.org/D155511
2023-07-18 11:34:21 -05:00
Joseph Huber
5db39796bf [libc] Support timing information in libc tests
This patch adds the necessary support to provide timing information in
`libc` tests. This is useful for determining which tests look what
amount of time. We also can use this as a test basis for providing more
fine-grained timing when implementing things on the GPU.

The main difficulty with this is the fact that the AMDGPU fixed
frequency clock operates at an unknown frequency. We need to read this
on a per-card basis from the driver and then copy it in. NVPTX on the
other hand has a fixed clock at a resolution of 1ns. I have also
increased the resolution of the print-outs as the majority of these are
below a millisecond for me.

Reviewed By: JonChesterfield

Differential Revision: https://reviews.llvm.org/D154446
2023-07-05 14:27:08 -05:00
Siva Chandra
3db36d6a9b [libc] Initiliaze the global pointer in riscv startup code.
Reviewed By: mikhail.ramalho

Differential Revision: https://reviews.llvm.org/D151539
2023-07-05 07:32:31 +00:00
Jun Zhang
ce378fcb9e
[libc][NFC] Simplify return value logic in set_thread_ptr()
Signed-off-by: Jun Zhang <jun@junz.org>

Differential Revision: https://reviews.llvm.org/D153572
2023-06-23 00:47:48 +08:00
Joseph Huber
ee6ace27e0 [libc] Remove disabled pass after performance improvement
This pass used to cause huge compile time regressions, That has been
address and can now be re-added.

Differential Revision: https://reviews.llvm.org/D153374
2023-06-20 15:48:02 -05:00
Joseph Huber
964a535bfa [libc] Remove flexible array and replace with a template
Currently the implementation of the RPC interface requires a flexible
struct. This caused problems when compilling the RPC server with GCC as
would be required if trying to export the RPC server interface. This
required that we either move to the `x[1]` workaround or make it a
template parameter. While just using `x[1]` would be much less noisy,
this is technically undefined behavior. For this reason I elected to use
templates.

The downside to using templates is that the server code must now be able
to handle multiple different types at runtime. I was unable to find a
good solution that didn't rely on type erasure so I simply branch off of
the given value.

Reviewed By: JonChesterfield

Differential Revision: https://reviews.llvm.org/D153304
2023-06-20 15:22:37 -05:00
Joseph Huber
5a8fc41937 [libc] Disable atomic optimizations for libc AMDGPU builds
Recently the AMDGPU backend automatically enables a pass to optimize
atomics. This results in the LTO build taking about 10x longer in all
cases. For now we disable this by default as was the case before the
patch in D152649.

Reviewed By: lntue

Differential Revision: https://reviews.llvm.org/D153232
2023-06-19 03:25:51 -05:00
Joseph Huber
ad00a3db4d [libc][AMDGPU] Disable the AMDGPU backend's ctor/dtor lowering for libc
The AMDGPU backend has a built-in pass to lower constructors. We do this
manually in the `start.cpp` implementation so we can disable this to
keep the binaries smaller.

Differential Revision: https://reviews.llvm.org/D151213
2023-05-23 09:20:41 -05:00
Joseph Huber
30093d6be2 [libc][obvious] Fix undefined variable after name change
I forgot that we still used these variables in the loaders.

Differential Revision: https://reviews.llvm.org/D150362
2023-05-11 09:00:08 -05:00
Jon Chesterfield
bbeae142bf [libc][rpc] Allocate a single block of shared memory instead of three
Allows moving the pointer swap between server and client into reset.
Single allocation simplifies whatever allocates the client/server, currently
the libc loaders.

Reviewed By: jhuber6

Differential Revision: https://reviews.llvm.org/D150337
2023-05-11 03:04:56 +01:00
Jon Chesterfield
f497611f43 [libc][rpc] Allocate locks array within process
Replaces the globals currently used. Worth changing to a bitmap
before allowing runtime number of ports >> 64. One bit per port is likely
to be cheap enough that sizing for the worst case is always fine, otherwise
in the future we can change to dynamically allocating it.

Reviewed By: jhuber6

Differential Revision: https://reviews.llvm.org/D150309
2023-05-11 00:41:51 +01:00
Joseph Huber
aea866c12c [libc] Support concurrent RPC port access on the GPU
Previously we used a single port to implement the RPC. This was
sufficient for single threaded tests but can potentially cause deadlocks
when using multiple threads. The reason for this is that GPUs make no
forward progress guarantees. Therefore one group of threads waiting on
another group of threads can spin forever because there is no guarantee
that the other threads will continue executing. The typical workaround
for this is to allocate enough memory that a sufficiently large number
of work groups can make progress. As long as this number is somewhat
close to the amount of total concurrency we can obtain reliable
execution around a shared resource.

This patch enables using multiple ports by widening the arrays to a
predetermined size and indexes into them. Empty ports are currently
obtained via a trivial linker scan. This should be imporoved in the
future for performance reasons. Portions of D148191 were applied to
achieve parallel support.

Depends on D149581

Reviewed By: JonChesterfield

Differential Revision: https://reviews.llvm.org/D149598
2023-05-05 10:12:19 -05:00
Joseph Huber
901266dad3 [libc] Change GPU startup and loader to use multiple kernels
The GPU has a different execution model to standard `_start`
implementations. On the GPU, all threads are active at the start of a
kernel. In order to correctly intitialize and call the constructors we
want single threaded semantics. Previously, this was done using a
makeshift global barrier with atomics. However, it should be easier to
simply put the portions of the code that must be single threaded in
separate kernels and then call those with only one thread. Generally,
mixing global state between kernel launches makes optimizations more
difficult, similarly to calling a function outside of the TU, but for
testing it is better to be correct.

Depends on D149527 D148943

Reviewed By: JonChesterfield

Differential Revision: https://reviews.llvm.org/D149581
2023-05-04 19:31:41 -05:00
Joseph Huber
507edb52f9 [libc] Enable multiple threads to use RPC on the GPU
The execution model of the GPU expects that groups of threads will
execute in lock-step in SIMD fashion. It's both important for
performance and correctness that we treat this as the smallest possible
granularity for an RPC operation. Thus, we map multiple threads to a
single larger buffer and ship that across the wire.

This patch makes the necessary changes to support executing the RPC on
the GPU with multiple threads. This requires some workarounds to mimic
the model when handling the protocol from the CPU. I'm not completely
happy with some of the workarounds required, but I think it should work.

Uses some of the implementation details from D148191.

Reviewed By: JonChesterfield

Differential Revision: https://reviews.llvm.org/D148943
2023-05-04 19:31:41 -05:00
Joseph Huber
2e1c0ec629 [libc] Support global constructors and destructors on NVPTX
This patch adds the necessary hacks to support global constructors and
destructors. This is an incredibly hacky process caused by the primary
fact that Nvidia does not provide any binary tools and very little
linker support. We first had to emit references to these functions and
their priority in D149451. Then we dig them out of the module once it's
loaded to manually create the list that the linker should have made for
us. This patch also contains a few Nvidia specific hacks, but it passes
the test, albeit with a stack size warning from `ptxas` for the
callback. But this should be fine given the resource usage of a common
test.

This also adds a dependency on LLVM to the NVPTX loader, which hopefully doesn't
cause problems with our CUDA buildbot.

Depends on D149451

Reviewed By: tra

Differential Revision: https://reviews.llvm.org/D149527
2023-05-04 07:13:00 -05:00
Joseph Huber
1b823abea7 [libc] Add support for global ctors / dtors for AMDGPU
This patch makes the necessary changes to support calling global
constructors and destructors on the GPU. The patch in D149340 allows the
`lld` linker to create the symbols pointing us to these globals. These
should be executed by a single thread, which is more difficult on the
GPU because all threads are active. I chose to use an atomic counter to
sync every thread on the GPU. This is very slow if you use more than a
few thousand threads, but for testing purposes it should be sufficient.

Depends on D149340 D149363

Reviewed By: sivachandra

Differential Revision: https://reviews.llvm.org/D149398
2023-04-29 08:40:20 -05:00
Joseph Huber
50445dff43 [libc] Add more utility functions for the GPU
This patch adds extra intrinsics for the GPU. Some of these are unused
for now but will be used later. We use these currently to update the
`RPC` handling. Currently, every thread can update the RPC client, which
isn't correct. This patch adds code neccesary to allow a single thread
to perfrom the write while the others wait.

Feedback is welcome for the naming of these functions. I'm copying the
OpenMP nomenclature where we call an AMD `wavefront` or NVIDIA `warp` a
`lane`.

Reviewed By: tra

Differential Revision: https://reviews.llvm.org/D148810
2023-04-24 15:47:53 -05:00
Joseph Huber
d0ff5e4030 [libc] Update RPC interface for system utilities on the GPU
This patch reworks the RPC interface to allow more generic memory
operations using the shared better. This patch decomposes the entire RPC
interface into opening a port and calling `send` or `recv` on it.

The `send` function sends a single packet of the length of the buffer.
The `recv` function is paired with the `send` call to then use the data.
So, any aribtrary combination of sending packets is possible. The only
restriction is that the client initiates the exchange with a `send`
while the server consumes it with a `recv`.

The operation of this is driven by two independent state machines that
tracks the buffer ownership during loads / stores. We keep track of two
so that we can transition between a send state and a recv state without
an extra wait. State transitions are observed via bit toggling, e.g.

This interface supports an efficient `send -> ack -> send -> ack -> send`
interface and allows for the last send to be ignored without checking
the ack.

A following patch will add some more comprehensive testing to this interface. I
I informally made an RPC call that simply incremented an integer and it took
roughly 10 microsends to complete an RPC call.

Reviewed By: jdoerfert

Differential Revision: https://reviews.llvm.org/D148288
2023-04-19 20:02:31 -05:00
Joseph Huber
e2356fb07e [libc] Add special handling for CUDA PTX features
The NVIDIA compilation path requires some special options. This is
mostly because compilation is dependent on having a valid CUDA
toolchain. We don't actually need the CUDA toolchain to create the
exported `libcgpu.a` library because it's pure LLVM-IR. However, for
some language features we need the PTX version to be set. This is
normally set by checking the CUDA version, but without one installed it
will fail to build. We instead choose a minimum set of features on the
desired target, inferred from
https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#release-notes
and the PTX refernece for functions like `nanosleep`.

Reviewed By: tianshilei1992

Differential Revision: https://reviews.llvm.org/D148532
2023-04-17 11:51:34 -05:00
Mikhail R. Gadelha
5b22df9984 [libc][NFC] Standardize missing syscalls error messages.
This patch standardizes the error messages when a syscall is not
available to be in the format: "ABC and DEF syscalls are not available."

Reviewed By: sivachandra

Differential Revision: https://reviews.llvm.org/D148373
2023-04-17 10:17:26 -03:00
Joseph Huber
9f5c6dcf59 [libc] Search for the CUDA patch explicitly when testing
The packaged version of the `libc` library does not depend on the CUDA
installation because it only uses `clang` and emits LLVM-IR. However,
for testing we directly need the CUDA toolkit to emit and execute the
files. This patch explicitly passes `--cuda-path` to the relevant
compilations for NVPTX testing.

Reviewed By: tra

Differential Revision: https://reviews.llvm.org/D147653
2023-04-05 15:14:47 -05:00
Joseph Huber
58f5e5e6b0 [libc] Implement the RPC client / server for NVPTX
This patch adds the necessary code to impelement the existing RPC client
/ server interface when targeting NVPTX GPUs. This follows closely to
the implementation in the AMDGPU version. This does not yet enable unit
testing as the `nvlink` linker does not support static libraries. So
that will need to be worked around.

I am ignoring the RPC duplication between the AMDGPU and NVPTX loaders. This
will be changed completely later so there's no point unifying the code at this
stage. The implementation was tested manually with the following file and
compilation flags.

```
namespace __llvm_libc {
void write_to_stderr(const char *msg);
void quick_exit(int);
} // namespace __llvm_libc

using namespace __llvm_libc;

int main(int argc, char **argv, char **envp) {
  for (int i = 0; i < argc; ++i) {
    write_to_stderr(argv[i]);
    write_to_stderr("\n");
  }
  quick_exit(255);
}
```

```
$ clang++ crt1.o rpc_client.o quick_exit.o io.o main.cpp --target=nvptx64-nvidia-cuda -march=sm_70 -o image
$ ./nvptx_loader image 1 2 3
image
1
2
3
$ echo $?
255
```

Depends on D146681

Reviewed By: jdoerfert

Differential Revision: https://reviews.llvm.org/D146846
2023-03-24 20:04:43 -05:00
Joseph Huber
1fce1d341b [libc] Use nvptx_kernel attribute in NVPTX startup code
Summary:
A recent patch allowed us to emit a callable kernel from freestanding
NVPTX code. This allows us to move away from using the CUDA language.
This has several advantages in that it works around an entire assortment
of errors I was seeing while implementing RPC for Nvidia.
2023-03-24 14:46:26 -05:00
Joseph Huber
ae63b1a576 [libc] Adjust NVPTX startup code
Summary:
The startup code needs to include the environment pointer so we add this
to the arguments. Also we need to ensure that the `crt1.o` file is made
with `-fgpu-rdc` set so we can actually use it without undefined
reference errors.
2023-03-22 20:08:08 -05:00
Joseph Huber
ebcc6dba5f [libc] Don't install the GPU startup code for now
Summary:
This startup code is only intended to be used internally, we shouldn't
export it under a conflicting name. In the future we may package this in
an exportable format.
2023-03-21 21:01:27 -05:00
Joseph Huber
6bd4d717d5 [libc] Add environment variables to GPU libc test for AMDGPU
This patch performs the same operation to copy over the `argv` array to
the `envp` array. This allows the GPU tests to use environment
variables.

Reviewed By: sivachandra

Differential Revision: https://reviews.llvm.org/D146322
2023-03-20 13:16:58 -05:00
Joseph Huber
39e91098b5 [libc] Enable integration tests targeting the GPU
This patch enables integration tests running on the GPU. This uses the
RPC interface implemented in D145913 to compile the necessary
dependencies for the integration test object. We can then use this to
compile the objects for the GPU directly and execute them using the AMD
HSA loader combined with its RPC server. For example, the compiler is
performing the following actions to execute the integration tests.

```
$ clang++ --target=amdgcn-amd-amdhsa -mcpu=gfx1030 -nostdlib -flto -ffreestanding \
    crt1.o io.o quick_exit.o test.o rpc_client.o args_test.o -o image
$ ./amdhsa_loader image 1 2 5
args_test.cpp:24: Expected 'my_streq(argv[3], "3")' to be true, but is false
```

This currently only works with a single threaded client implementation
running on AMDGPU. Further work will implement multiple clients for AMD
and the ability to run on NVPTX as well.

Depends on D145913

Reviewed By: sivachandra, JonChesterfield

Differential Revision: https://reviews.llvm.org/D146256
2023-03-17 12:55:32 -05:00
Joseph Huber
8e4f9b1fcb [libc] Add initial support for an RPC mechanism for the GPU
This patch adds initial support for an RPC client / server architecture.
The GPU is unable to perform several system utilities on its own, so in
order to implement features like printing or memory allocation we need
to be able to communicate with the executing process. This is done via a
buffer of "sharable" memory. That is, a buffer with a unified pointer
that both the client and server can use to communicate.

The implementation here is based off of Jon Chesterfields minimal RPC
example in his work. We use an `inbox` and `outbox` to communicate
between if there is an RPC request and to signify when work is done.
We use a fixed-size buffer for the communication channel. This is fixed
size so that we can ensure that there is enough space for all
compute-units on the GPU to issue work to any of the ports. Right now
the implementation is single threaded so there is only a single buffer
that is not shared.

This implementation still has several features missing to be complete.
Such as multi-threaded support and asynchrnonous calls.

Depends on D145912

Reviewed By: sivachandra

Differential Revision: https://reviews.llvm.org/D145913
2023-03-17 12:55:31 -05:00
Joseph Huber
a704c312f1 [libc] Add missing dependencies to RISC-V startup implementation
Summary:
Just like the last patch, the threads and envrion dependencies were
missing. This lead to linker failures when building the tests.
2023-03-16 09:13:18 -05:00
Joseph Huber
501a8724bd [libc] Add missing environ dependency to AArch64 startup implementation
Summary:
Just like the last patch, this dependency was missing. This lead to
linker failures when building the tests.
2023-03-16 08:06:14 -05:00
Joseph Huber
2389f00019 [libc] Add missing threads dependency to AArch64 startup implementation
Summary:
The changes in D146184 made the integration tests use the inhereted
dependencies from the startup code like a normal target. For the AArch64
target this resulted in the threads depenency not being pulled in
because it was not present in the original code.
2023-03-16 08:00:14 -05:00
Siva Chandra Reddy
5b1ad43c2b [libc] Declare __dso_handle in the integration test instead of startup.
Fixes #61355. The __dso_handle decl was introduced incorrectly into the startup
objects during the integration test cleanup which moved the integration tests
away from using an artificial sysroot to using -nostdlib. Having it in the
startup creates the duplicate symbol error when one does not use -nostdlib.
Since this is an integration test only problem, it is meaningful to keep it in
the integration test anyway.

Differential Revision: https://reviews.llvm.org/D145898
2023-03-13 07:47:00 +00:00
Siva Chandra
cf90633cf2 [libc] Extend the linux thread implementation for riscv64.
Also, added riscv64 startup code for static linking which is used
by the integration tests. Functions from the C standard threads
library have been enabled.

Reviewed By: mikhail.ramalho

Differential Revision: https://reviews.llvm.org/D145670
2023-03-09 16:58:48 +00:00
Siva Chandra Reddy
a7d869aabb [libc] Simplify integration tests by eliminating the artificial sysroot.
The test binaries are built like any other executable but with two
additional linker options -static and -nostdlib.

Reviewed By: jhuber6

Differential Revision: https://reviews.llvm.org/D145298
2023-03-06 07:37:48 +00:00
Joseph Huber
6641f8da73 [libc] Fix amdgpu startup code flags
Summary:
Currently AMDGPU only barely supports cross-TU ELF linking. Full linking
is usually done via LTO. This requires passing the architecture to the
link job. This is done automatically via `-flto` since D144505. Add this
to the link options.
2023-02-22 11:38:26 -06:00
Joseph Huber
d51d2b5909 [libc] Support add_object_library for the GPU build
This patch unifies the handling of generating the GPU build targets
between the `add_entrypoint_library` and the `add_object_library`
functions. The `_build_gpu_objects` function will create two targets.
One contains a single object file with several GPU binaries embedded in
it, a so-called fatbinary. The other is a direct compile of the
supported target to be used internally only. This patch pulls out some
of the properties logic so that we can handle both more easily. This
patch also required adding an ovverride  `NO_GPU_BUILD` for cases when
we only want to build the source file as normal.

Reviewed By: sivachandra

Differential Revision: https://reviews.llvm.org/D144214
2023-02-20 09:37:18 -06:00
Joseph Huber
fa34b9e032 [libc] Add startup code implementation for GPU targets
This patch introduces startup code for executing `main` on a device
compiled for the GPU. We will primarily use this to run standalone
integration tests on the GPU. The actual execution of this routine will
need to be provided by a `loader` utility to bootstrap execution on the
GPU.

Reviewed By: sivachandra

Differential Revision: https://reviews.llvm.org/D143212
2023-02-07 11:36:16 -06:00
Siva Chandra Reddy
9b4999cbea [libc] Cleanup the CMake infrastructure to add startup objects.
Instead of using a custom target to copy the startup object file to a
file with the desired name, a normal object library with a special
property is used.

Follow up patches will do more cleanup wrt how the startup objects are
used in integration tests.

Reviewed By: jhuber6

Differential Revision: https://reviews.llvm.org/D143464
2023-02-07 16:35:46 +00:00
Siva Chandra Reddy
b875defc55 [libc] Build two different static archives libc.a and libm.a under full build.
We currently put everything in one single archive libc.a which breaks in
certain situations where the compiler drivers expect libm.a also. With
this change, we separate out libc.a and libm.a functions as is done
conventionally and put them in two different static archives.

One will now have to build two targets, `libc` and `libm` which produce
`libc.a` and `libm.a` respectively. Under default build, one still builds only
one target named `libc` which produces `libllvmlibc.a`.

Reviewed By: jhuber6

Differential Revision: https://reviews.llvm.org/D143005
2023-01-31 21:45:08 +00:00
Siva Chandra Reddy
a439c4afdc [libc][Obvious] Address few GCC warnings. 2023-01-09 20:54:13 +00:00
Siva Chandra Reddy
9a07780687 [libc][NFC] Rename "loader" to "startup".
Reviewed By: lntue

Differential Revision: https://reviews.llvm.org/D140049
2022-12-15 19:54:21 +00:00