Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions llvm/docs/AMDGPUUsage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1179,6 +1179,51 @@ is conservatively correct for OpenCL.
other operations within the same address space.
======================= ===================================================

Target Types
------------

The AMDGPU backend implements some target extension types.

.. _amdgpu-types-named-barriers:

Named Barriers
~~~~~~~~~~~~~~

Named barriers are fixed function hardware barrier objects that are available
in gfx12.5+ in addition to the traditional default barriers.

In LLVM IR, named barriers are represented by global variables of type
``target("amdgcn.named.barrier", 0)`` in the LDS address space. Named barrier
global variables do not occupy actual LDS memory, but their lifetime and
allocation scope matches that of global variables in LDS. Programs in LLVM IR
refer to named barriers using pointers.

The following named barrier types are supported in global variables, defined
recursively:

* a single, standalone ``target("amdgcn.named.barrier", 0)``
* an array of supported types
* a struct containing a single element of supported type
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Presumably an array of supported types is recursively itself a supported type that can occur as the single element in a struct type? Also, what stops us from allowing two fields which are both arrays in a struct?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes to the first question.

To the second question: We could do that, it just didn't seem important and would be additional effort. The reason for allowing a struct is to allow wrapping types in C++ structs/classes.


.. code-block:: llvm

@bar = addrspace(3) global target("amdgcn.named.barrier", 0) undef
@foo = addrspace(3) global [2 x target("amdgcn.named.barrier", 0)] undef
@baz = addrspace(3) global { target("amdgcn.named.barrier", 0) } undef

...

%foo.i = getelementptr [2 x target("amdgcn.named.barrier", 0)], ptr addrspace(3) @foo, i32 0, i32 %i
call void @llvm.amdgcn.s.barrier.signal.var(ptr addrspace(3) %foo.i, i32 0)

Named barrier types may not be used in ``alloca``.

Named barriers do not have an underlying byte representation.
It is undefined behavior to use a pointer to any part of a named barrier object
as the pointer operand of a regular memory access instruction or intrinsic.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we need to add something to say the pointer has to be used directly, so cannot be offset (gep) or undergo any kind of manipulation such as inttoptr/ptrtoint?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It actually can undergo that kind of manipulation. That was a goal of the design.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you can offset within a contiguous span of objects of the same type, but taking a difference of two such pointers results in an unspecified integer value.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.

Pointers to named barrier objects are intended to be used with dedicated
intrinsics. Reading from or writing to such pointers is undefined behavior.

LLVM IR Intrinsics
------------------

Expand Down
Loading