Skip to content

[MLIR] Add C API for Enzyme dialect (MLIRCAPIEnzyme)#2859

Open
agarret7 wants to merge 7 commits into
EnzymeAD:mainfrom
agarret7:mlir-c-api
Open

[MLIR] Add C API for Enzyme dialect (MLIRCAPIEnzyme)#2859
agarret7 wants to merge 7 commits into
EnzymeAD:mainfrom
agarret7:mlir-c-api

Conversation

@agarret7

@agarret7 agarret7 commented Jun 6, 2026

Copy link
Copy Markdown

Add C API for Enzyme MLIR dialect (MLIRCAPIEnzyme)

The Enzyme MLIR dialect has no C API, making it inaccessible to
foreign-language bindings (Rust, Python, etc.) without depending on C++
headers. This PR adds the missing layer, following the same pattern used
by upstream MLIR's own dialect C APIs (mlir-c/Dialect/Arith.h, etc.).

What's added

  • Dialect registrationMLIR_DECLARE/DEFINE_CAPI_DIALECT_REGISTRATION
    so the dialect can be loaded into an MlirContext from C
  • enzymeActivityAttrGet — constructs an enzyme.activity attribute
    from a C-side EnzymeActivity enum
  • enzymeAutoDiffOpCreate / enzymeForwardDiffOpCreate — construct
    unattached enzyme.autodiff / enzyme.fwddiff ops from C, taking the
    same arguments as the TableGen-generated C++ builders
  • Build systemIntegrations/c/CMakeLists.txt with an
    add_mlir_public_c_api_library(MLIRCAPIEnzyme ...) target, wired into
    Integrations/CMakeLists.txt and MLIR/CMakeLists.txt

Not included (deferred)

enzymeRegisterPasses is not included because MLIREnzymeTransforms
depends on MLIREnzymeAnalysis, which currently fails to build due to a
pre-existing MLIR API change (getSuccessorInputs
getSuccessorRegions), tracked in #2858.

Testing

MLIRCAPIEnzyme builds cleanly against LLVM/MLIR 22. The round-trip test will pass once the MLIREnzymeAnalysis build failures are resolved.

Edit: The test/MLIR/CAPI/roundtrip.mlir I included is a round-trip test for the ops themselves, not the C API. The existing ForwardMode/ReverseMode tests already cover that. A proper C API test requires a compiled C binary and lit infrastructure that doesn't exist in Enzyme's test suite yet. I've removed the placeholder. Happy to add proper C test infrastructure as a follow-up if that's the preferred direction.

@agarret7
agarret7 marked this pull request as draft June 7, 2026 02:35
Comment thread enzyme/Enzyme/MLIR/Integrations/c/EnzymeMLIR.cpp Outdated
@wsmoses
wsmoses requested a review from mofeing June 7, 2026 05:03

@mofeing mofeing left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lgtm

Comment thread enzyme/Enzyme/MLIR/Integrations/c/EnzymeMLIR.cpp Outdated
agarret7 added 3 commits June 8, 2026 11:03
Adds the missing C API layer for the Enzyme MLIR dialect, following the
same pattern as upstream MLIR's mlir-c/ libraries:

- `MLIR_DECLARE/DEFINE_CAPI_DIALECT_REGISTRATION` for the enzyme dialect
- `enzymeActivityAttrGet` — constructs an `enzyme.activity` attr from the
  C-side `EnzymeActivity` enum (enzyme_active, enzyme_dup, enzyme_const, …)
- `enzymeAutoDiffOpCreate` / `enzymeForwardDiffOpCreate` — construct
  unattached `enzyme.autodiff` / `enzyme.fwddiff` ops from C
- `Integrations/c/CMakeLists.txt` wiring up `MLIRCAPIEnzyme` as an
  `add_mlir_public_c_api_library` target
- `Integrations/CMakeLists.txt` + hook in `MLIR/CMakeLists.txt`

This enables foreign-language bindings (Rust, Python, etc.) to emit
Enzyme dialect ops without depending on C++ headers.
@wsmoses

wsmoses commented Jun 8, 2026

Copy link
Copy Markdown
Member

@mofeing note once this lands, we should adapt reactantextra to remove its copy of similar apis

@wsmoses

wsmoses commented Jun 8, 2026

Copy link
Copy Markdown
Member

@agarret7 minor, but clang-format fails

@agarret7

agarret7 commented Jun 8, 2026

Copy link
Copy Markdown
Author

Updated this PR with the following additions:

  • MLIR_CAPI_EXPORTED on all function definitions
  • Pass creation functions: enzymeCreateBatchPass, enzymeCreateBatchDiffPass, enzymeCreateConvertEnzymeToMemRefPass, enzymeCreateRemoveUnusedEnzymeOpsPass,
    enzymeBatchOpCreate constructor
  • Rebased onto current main

Motivation: I'm planning a PR to Melior to expose Enzyme-backed autodiff. Melior upgraded to MLIR 22 a couple months ago, so I validated this C API end-to-end against MLIR 22 via a small Rust test harness using bindgen.

Comment thread enzyme/Enzyme/MLIR/Integrations/c/EnzymeMLIR.cpp

@wsmoses wsmoses left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

sorry one more nit for the activity one, then lgtm

@wsmoses wsmoses left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

tangent [and @mofeing feel free to offer suggestions]

but can you also add this to the bazel build system too?

@agarret7

Copy link
Copy Markdown
Author

tangent [and @mofeing feel free to offer suggestions]

but can you also add this to the bazel build system too?

I'm not super familiar with bazel, what would that entail?

@agarret7

agarret7 commented Jun 12, 2026

Copy link
Copy Markdown
Author

tangent [and @mofeing feel free to offer suggestions]
but can you also add this to the bazel build system too?

I'm not super familiar with bazel, what would that entail?

Looking at enzyme/BUILD, the CInterface target (BUILD:1052-1053) already builds Integrations/c/EnzymeMLIR.{cpp,h}. Maybe no changes are needed for to add to bazel? I don't have it set up locally to confirm with a build, happy to if someone can point me at what is needed to test it.

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