nir: Add unified atomics
authorAlyssa Rosenzweig <alyssa@rosenzweig.io>
Mon, 8 May 2023 19:29:31 +0000 (15:29 -0400)
committerMarge Bot <emma+marge@anholt.net>
Fri, 12 May 2023 20:39:46 +0000 (20:39 +0000)
commitd51bc95837620a774f6d2b04228f340dfc536fc6
tree731a32a59c52116d9cd772f840184d9eb3095d8e
parent88f6d7f4bdf90bcfdb17e4aadddec3c855a12b13
nir: Add unified atomics

Currently, we have an atomic intrinsic for each combination of memory type
(global, shared, image, etc) and atomic operation (add, sub, etc). So for m
types of memory supported by the driver and n atomic opcodes, the driver has to
handle O(mn) intrinsics. This makes a total mess in every single backend I've
looked at, without fail.

It would be a lot nicer to unify the intrinsics. There are two obvious ways:

1. Make the memory type a constant index, keep different intrinsics for
   different operations. The problem with this is that different memory types
   imply different intrinsic signatures (number of sources, etc).  As an
   example, it doesn't make sense to unify global_atomic_amd with
   global_atomic_2x32, as an example. The first takes 3 scalar sources, the
   second takes 1 vector and 1 scalar. Also, in any single backend, there are a
   lot more operations than there are memory types.

2. Make the opcode a constant index, keep different intrinsics for different
   operations. This works well, with one exception: compswap and fcompswap
   take an extra argument that other atomics don't, so there's an extra axis of
   variation for the intrinsic signatures.

So, the solution is to have 2 intrinsics for each memory type -- for atomics
taking 1 argument and atomics taking 2 respectively. Both of these intrinsics
take an nir_atomic_op enum to describe its operation. We don't use a nir_op for
this purpose, as there are some atomics (cmpxchg, inc_wrap, etc) that don't
cleanly map to any ALU op and it would be weird to force it.

The plan is to transition to these new opcodes gradually. This series adds a
lowering pass producing these opcodes from the existing opcodes, so that
backends can opt-in to the new forms one-by-one. Then we can convert backends
separately without any cross-tree flag day. Once everything is converted, we can
convert the producers and core NIR as a flag day, but we have far fewer
producers than backends so this should be fine. Finally we can drop the old
stuff.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Reviewed-by: Jesse Natalie <jenatali@microsoft.com>
Reviewed-by: Timur Kristóf <timur.kristof@gmail.com>
Reviewed-by: Rob Clark <robclark@freedesktop.org>
Reviewed-by: Faith Ekstrand <faith.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22914>
src/compiler/nir/nir.c
src/compiler/nir/nir.h
src/compiler/nir/nir_divergence_analysis.c
src/compiler/nir/nir_gather_info.c
src/compiler/nir/nir_intrinsics.py
src/compiler/nir/nir_lower_io.c
src/compiler/nir/nir_opt_load_store_vectorize.c
src/compiler/nir/nir_print.c