Skip to content

[triton-ext] Pass a single PluginInfo * pointer#9748

Merged
ThomasRaoux merged 8 commits into
triton-lang:mainfrom
abrown:plugin-single-struct-rebased
Mar 25, 2026
Merged

[triton-ext] Pass a single PluginInfo * pointer#9748
ThomasRaoux merged 8 commits into
triton-lang:mainfrom
abrown:plugin-single-struct-rebased

Conversation

@abrown
Copy link
Copy Markdown
Contributor

@abrown abrown commented Mar 17, 2026

This changes how we pass data between Triton plugins and Triton. Instead of implementing multiple functions with various signatures, we collect all the pointers into a single struct PluginInfo and pass this as a pointer across the host-plugin boundary when tritonGetPluginInfo is called. This simplifies things on both the host side (Triton has less ABI surface to worry about) and on the plugin side (less intermediate registration into maps). It also ensures that what we pass is extern "C": we now fully rely on the C ABI, which should avoid a whole category of potential problems down the line.

This approach--passing a single struct across the API--is taken from how LLVM implements plugins. E.g., MLIR's DialectPlugin and PassPlugin do exactly this. Triton's case is a bit more tricky since we can export multiple passes and dialects from a single plugin. But since libraries are loaded via LLVM's
DynamicLibrary::getPermanentLibrary, we expect these plugins to have a lifetime spanning the entire program. In other words, the PluginInfo* pointer would be leaked if we attempted to teardown Triton mid-process (?) but we simply don't do this.

This change also allows us to pass multiple plugins to Triton: we replace TRITON_PASS_PLUGIN_PATH with a colon-separated TRITON_PLUGIN_PATHS. I tested this over in triton-ext and it works as expected.

For the rationale behind these changes, see the Triton Extensions RFCv2 document.

@abrown abrown requested review from lezcano and ptillet as code owners March 17, 2026 15:53
Comment thread python/src/passes.cc Outdated
abrown added a commit to abrown/triton-ext that referenced this pull request Mar 17, 2026
In [#9748], I took a stab at reworking the Triton API with some of the
proposals in the [RFCv2] document. This change adapts triton-ext to use
that new API. The crux of this is that we return a `PluginInfo *`
pointer from `Export.cpp` with all of the plugin metadata in one place.

This leaves a couple of items in-progress for future commits:
- this keeps the internal `unordered_map` registration which is dynamic
  enough that we need to heap-allocate the `struct PluginInfo`; ideally
  we should be doing this all statically
- we do not have a great way to pass through the plugin name and version
  to the `TritonExtensionSupport` library; we could do this dynamically
  with another internal `exportPluginName` function but, again, it feels
  like there must be some way to do this more statically.

[#9748]: triton-lang/triton#9748
[RFCv2]: https://docs.google.com/document/d/1XlxNYahzpHgU3gg0Y8ayopTWK7GRy8eQ5ExDtXt6GZ4
abrown added a commit to abrown/triton-ext that referenced this pull request Mar 17, 2026
In [#9748], I took a stab at reworking the Triton API with some of the
proposals in the [RFCv2] document. This change adapts triton-ext to use
that new API. The crux of this is that we return a `PluginInfo *`
pointer from `Export.cpp` with all of the plugin metadata in one place.

This leaves a couple of items in-progress for future commits:
- this keeps the internal `unordered_map` registration which is dynamic
  enough that we need to heap-allocate the `struct PluginInfo`; ideally
  we should be doing this all statically
- we do not have a great way to pass through the plugin name and version
  to the `TritonExtensionSupport` library; we could do this dynamically
  with another internal `exportPluginName` function but, again, it feels
  like there must be some way to do this more statically.

[#9748]: triton-lang/triton#9748
[RFCv2]: https://docs.google.com/document/d/1XlxNYahzpHgU3gg0Y8ayopTWK7GRy8eQ5ExDtXt6GZ4
Comment thread include/triton/Tools/PluginUtils.h Outdated
abrown added 2 commits March 18, 2026 09:32
This changes how we pass data between Triton plugins and Triton. Instead
of implementing multiple functions with various signatures, we collect
all the pointers into a single `struct PluginInfo` and pass this as a
pointer across the host-plugin boundary when `tritonGetPluginInfo` is
called. This simplifies things on both the host side (Triton has less
ABI surface to worry about) and on the plugin side (less intermediate
registration into maps). It also ensures that what we pass is `extern
"C"`: we now fully rely on the C ABI, which should avoid a whole
category of potential problems down the line.

This approach--passing a single struct across the API--is taken from how
LLVM implements plugins. E.g., MLIR's [`DialectPlugin`] and
[`PassPlugin`] do exactly this. Triton's case is a bit more tricky since
we can export multiple passes and dialects from a single plugin. But
since libraries are loaded via LLVM's
`DynamicLibrary::getPermanentLibrary`, we expect these plugins to have a
lifetime spanning the entire program. In other words, the `PluginInfo*`
pointer would be leaked if we attempted to teardown Triton mid-process
(?) but we simply don't do this.

This change also allows us to pass multiple plugins to Triton: we
replace `TRITON_PASS_PLUGIN_PATH` with a colon-separated
`TRITON_PLUGIN_PATHS`. I tested this over in `triton-ext` and it works
as expected.

For the rationale behind these changes, see the Triton Extensions
[RFCv2] document.

[`DialectPlugin`]: https://github.com/llvm/llvm-project/blob/80d6e0b8/mlir/include/mlir/Tools/Plugins/DialectPlugin.h
[`PassPlugin`]: https://github.com/llvm/llvm-project/blob/80d6e0b8/mlir/include/mlir/Tools/Plugins/PassPlugin.h
[RFCv2]: https://docs.google.com/document/d/1XlxNYahzpHgU3gg0Y8ayopTWK7GRy8eQ5ExDtXt6GZ4
@abrown abrown force-pushed the plugin-single-struct-rebased branch from 4d29cf9 to 39c1482 Compare March 18, 2026 16:33
Comment thread include/triton/Tools/PluginUtils.h Outdated
Comment thread include/triton/Tools/PluginUtils.h Outdated
Copy link
Copy Markdown
Collaborator

@ThomasRaoux ThomasRaoux left a comment

Choose a reason for hiding this comment

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

Looks like a good clean up to me

@abrown
Copy link
Copy Markdown
Contributor Author

abrown commented Mar 24, 2026

Looks like an unrelated build failure... can someone re-run?

@ThomasRaoux ThomasRaoux merged commit 283dc31 into triton-lang:main Mar 25, 2026
9 checks passed
@abrown abrown deleted the plugin-single-struct-rebased branch March 25, 2026 23:56
abrown added a commit to triton-lang/triton-ext that referenced this pull request Mar 26, 2026
In [#9748], I took a stab at reworking the Triton API with some of the
proposals in the [RFCv2] document. This change adapts triton-ext to use
that new API. The crux of this is that we return a `PluginInfo *`
pointer from `Export.cpp` with all of the plugin metadata in one place.

This leaves a couple of items in-progress for future commits:
- this keeps the internal `unordered_map` registration which is dynamic
  enough that we need to heap-allocate the `struct PluginInfo`; ideally
  we should be doing this all statically
- we do not have a great way to pass through the plugin name and version
  to the `TritonExtensionSupport` library; we could do this dynamically
  with another internal `exportPluginName` function but, again, it feels
  like there must be some way to do this more statically.

[#9748]: triton-lang/triton#9748
[RFCv2]: https://docs.google.com/document/d/1XlxNYahzpHgU3gg0Y8ayopTWK7GRy8eQ5ExDtXt6GZ4
abrown added a commit to abrown/triton that referenced this pull request Mar 26, 2026
In triton-lang#9748, the ability to return the created custom op was accidentally
removed. This change allows us to fallibly return the created
`mlir::Value` without altering the vector of passed `args`.
ThomasRaoux pushed a commit that referenced this pull request Mar 26, 2026
#9748 introduced some changes
to the custom ops API and dropped the return value. But the plugin
convention expects operands[0] to be a writable result slot. This adds
that return value for the added op back.
jvican pushed a commit to jvican/triton that referenced this pull request Mar 27, 2026
This changes how we pass data between Triton plugins and Triton. Instead
of implementing multiple functions with various signatures, we collect
all the pointers into a single `struct PluginInfo` and pass this as a
pointer across the host-plugin boundary when `tritonGetPluginInfo` is
called. This simplifies things on both the host side (Triton has less
ABI surface to worry about) and on the plugin side (less intermediate
registration into maps). It also ensures that what we pass is `extern
"C"`: we now fully rely on the C ABI, which should avoid a whole
category of potential problems down the line.

This approach--passing a single struct across the API--is taken from how
LLVM implements plugins. E.g., MLIR's [`DialectPlugin`] and
[`PassPlugin`] do exactly this. Triton's case is a bit more tricky since
we can export multiple passes and dialects from a single plugin. But
since libraries are loaded via LLVM's
`DynamicLibrary::getPermanentLibrary`, we expect these plugins to have a
lifetime spanning the entire program. In other words, the `PluginInfo*`
pointer would be leaked if we attempted to teardown Triton mid-process
(?) but we simply don't do this.

This change also allows us to pass multiple plugins to Triton: we
replace `TRITON_PASS_PLUGIN_PATH` with a colon-separated
`TRITON_PLUGIN_PATHS`. I tested this over in `triton-ext` and it works
as expected.

For the rationale behind these changes, see the Triton Extensions
[RFCv2] document.

[`DialectPlugin`]:
https://github.com/llvm/llvm-project/blob/80d6e0b8/mlir/include/mlir/Tools/Plugins/DialectPlugin.h
[`PassPlugin`]:
https://github.com/llvm/llvm-project/blob/80d6e0b8/mlir/include/mlir/Tools/Plugins/PassPlugin.h
[RFCv2]:
https://docs.google.com/document/d/1XlxNYahzpHgU3gg0Y8ayopTWK7GRy8eQ5ExDtXt6GZ4
jvican pushed a commit to jvican/triton that referenced this pull request Mar 27, 2026
…n-lang#9864)

triton-lang#9748 introduced some changes
to the custom ops API and dropped the return value. But the plugin
convention expects operands[0] to be a writable result slot. This adds
that return value for the added op back.
plotfi pushed a commit to plotfi/triton that referenced this pull request Apr 8, 2026
This changes how we pass data between Triton plugins and Triton. Instead
of implementing multiple functions with various signatures, we collect
all the pointers into a single `struct PluginInfo` and pass this as a
pointer across the host-plugin boundary when `tritonGetPluginInfo` is
called. This simplifies things on both the host side (Triton has less
ABI surface to worry about) and on the plugin side (less intermediate
registration into maps). It also ensures that what we pass is `extern
"C"`: we now fully rely on the C ABI, which should avoid a whole
category of potential problems down the line.

This approach--passing a single struct across the API--is taken from how
LLVM implements plugins. E.g., MLIR's [`DialectPlugin`] and
[`PassPlugin`] do exactly this. Triton's case is a bit more tricky since
we can export multiple passes and dialects from a single plugin. But
since libraries are loaded via LLVM's
`DynamicLibrary::getPermanentLibrary`, we expect these plugins to have a
lifetime spanning the entire program. In other words, the `PluginInfo*`
pointer would be leaked if we attempted to teardown Triton mid-process
(?) but we simply don't do this.

This change also allows us to pass multiple plugins to Triton: we
replace `TRITON_PASS_PLUGIN_PATH` with a colon-separated
`TRITON_PLUGIN_PATHS`. I tested this over in `triton-ext` and it works
as expected.

For the rationale behind these changes, see the Triton Extensions
[RFCv2] document.

[`DialectPlugin`]:
https://github.com/llvm/llvm-project/blob/80d6e0b8/mlir/include/mlir/Tools/Plugins/DialectPlugin.h
[`PassPlugin`]:
https://github.com/llvm/llvm-project/blob/80d6e0b8/mlir/include/mlir/Tools/Plugins/PassPlugin.h
[RFCv2]:
https://docs.google.com/document/d/1XlxNYahzpHgU3gg0Y8ayopTWK7GRy8eQ5ExDtXt6GZ4

(cherry picked from commit 283dc31)
plotfi pushed a commit to plotfi/triton that referenced this pull request Apr 8, 2026
This changes how we pass data between Triton plugins and Triton. Instead
of implementing multiple functions with various signatures, we collect
all the pointers into a single `struct PluginInfo` and pass this as a
pointer across the host-plugin boundary when `tritonGetPluginInfo` is
called. This simplifies things on both the host side (Triton has less
ABI surface to worry about) and on the plugin side (less intermediate
registration into maps). It also ensures that what we pass is `extern
"C"`: we now fully rely on the C ABI, which should avoid a whole
category of potential problems down the line.

This approach--passing a single struct across the API--is taken from how
LLVM implements plugins. E.g., MLIR's [`DialectPlugin`] and
[`PassPlugin`] do exactly this. Triton's case is a bit more tricky since
we can export multiple passes and dialects from a single plugin. But
since libraries are loaded via LLVM's
`DynamicLibrary::getPermanentLibrary`, we expect these plugins to have a
lifetime spanning the entire program. In other words, the `PluginInfo*`
pointer would be leaked if we attempted to teardown Triton mid-process
(?) but we simply don't do this.

This change also allows us to pass multiple plugins to Triton: we
replace `TRITON_PASS_PLUGIN_PATH` with a colon-separated
`TRITON_PLUGIN_PATHS`. I tested this over in `triton-ext` and it works
as expected.

For the rationale behind these changes, see the Triton Extensions
[RFCv2] document.

[`DialectPlugin`]:
https://github.com/llvm/llvm-project/blob/80d6e0b8/mlir/include/mlir/Tools/Plugins/DialectPlugin.h
[`PassPlugin`]:
https://github.com/llvm/llvm-project/blob/80d6e0b8/mlir/include/mlir/Tools/Plugins/PassPlugin.h
[RFCv2]:
https://docs.google.com/document/d/1XlxNYahzpHgU3gg0Y8ayopTWK7GRy8eQ5ExDtXt6GZ4

(cherry picked from commit 283dc31)
(cherry picked from commit 52372e7)
@plotfi plotfi mentioned this pull request Apr 8, 2026
atalman pushed a commit that referenced this pull request Apr 10, 2026
[triton-ext] Update plugin extension changes for release 3.7.x

cherry-picking the following plugin extension changes since January:

- **[triton-ext] Fix garbage string in reported errors (#9687)**
- **[triton-ext] add string arguments to addPass API (#9691)**
- **[triton-ext][FrontEnd] Custom DSL Plugin Ops (#9626)**
- **[triton-ext] Drop LLVM_BUILD_SHARED_LIBS, enable libtriton
visibility through TRITON_EXT_ENABLED (#9783)**
- **[triton-ext] Pass a single `PluginInfo *` pointer (#9748)**
- **[triton-ext] plugin extension's version check (#9937)**

---------

Co-authored-by: Andrew Brown <andrew@kernelize.ai>
Co-authored-by: Corbin Robeck <robeck@meta.com>
plognjen pushed a commit to plognjen/triton that referenced this pull request Apr 14, 2026
This changes how we pass data between Triton plugins and Triton. Instead
of implementing multiple functions with various signatures, we collect
all the pointers into a single `struct PluginInfo` and pass this as a
pointer across the host-plugin boundary when `tritonGetPluginInfo` is
called. This simplifies things on both the host side (Triton has less
ABI surface to worry about) and on the plugin side (less intermediate
registration into maps). It also ensures that what we pass is `extern
"C"`: we now fully rely on the C ABI, which should avoid a whole
category of potential problems down the line.

This approach--passing a single struct across the API--is taken from how
LLVM implements plugins. E.g., MLIR's [`DialectPlugin`] and
[`PassPlugin`] do exactly this. Triton's case is a bit more tricky since
we can export multiple passes and dialects from a single plugin. But
since libraries are loaded via LLVM's
`DynamicLibrary::getPermanentLibrary`, we expect these plugins to have a
lifetime spanning the entire program. In other words, the `PluginInfo*`
pointer would be leaked if we attempted to teardown Triton mid-process
(?) but we simply don't do this.

This change also allows us to pass multiple plugins to Triton: we
replace `TRITON_PASS_PLUGIN_PATH` with a colon-separated
`TRITON_PLUGIN_PATHS`. I tested this over in `triton-ext` and it works
as expected.

For the rationale behind these changes, see the Triton Extensions
[RFCv2] document.

[`DialectPlugin`]:
https://github.com/llvm/llvm-project/blob/80d6e0b8/mlir/include/mlir/Tools/Plugins/DialectPlugin.h
[`PassPlugin`]:
https://github.com/llvm/llvm-project/blob/80d6e0b8/mlir/include/mlir/Tools/Plugins/PassPlugin.h
[RFCv2]:
https://docs.google.com/document/d/1XlxNYahzpHgU3gg0Y8ayopTWK7GRy8eQ5ExDtXt6GZ4
plognjen pushed a commit to plognjen/triton that referenced this pull request Apr 14, 2026
…n-lang#9864)

triton-lang#9748 introduced some changes
to the custom ops API and dropped the return value. But the plugin
convention expects operands[0] to be a writable result slot. This adds
that return value for the added op back.
CRobeck added a commit to CRobeck/triton that referenced this pull request May 5, 2026
…n-lang#9864)

triton-lang#9748 introduced some changes
to the custom ops API and dropped the return value. But the plugin
convention expects operands[0] to be a writable result slot. This adds
that return value for the added op back.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants