diff --git a/tests/unit/test_fly_opt_tooling.py b/tests/unit/test_fly_opt_tooling.py new file mode 100644 index 00000000..eff2dd82 --- /dev/null +++ b/tests/unit/test_fly_opt_tooling.py @@ -0,0 +1,67 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2025 FlyDSL Project Contributors + +"""fly-opt tool usage guardrails.""" + +import os +from pathlib import Path +import subprocess + +import pytest + +pytestmark = [pytest.mark.l0_backend_agnostic] + +_REPO_ROOT = Path(__file__).resolve().parents[2] + + +def _fly_opt_path() -> Path: + configured = os.environ.get("FLYDSL_FLY_OPT") or os.environ.get("FLY_OPT") + candidates = [ + Path(configured) if configured else None, + _REPO_ROOT / "build-fly" / "bin" / "fly-opt", + ] + for candidate in candidates: + if candidate and candidate.is_file(): + return candidate + pytest.skip("fly-opt binary not available; set FLYDSL_FLY_OPT to run this regression") + + +def test_fly_opt_gpu_module_to_binary_has_llvm_translation(tmp_path): + """Regression for gpu-module-to-binary failing before target serialization. + + Without GPU-to-LLVMIR translations registered in fly-opt, this real + gpu-module-to-binary invocation fails with: + "missing LLVMTranslationDialectInterface registration for dialect for op: + gpu.module". + """ + + input_mlir = tmp_path / "kernel.mlir" + input_mlir.write_text( + '''module attributes {gpu.container_module} { + gpu.module @kernels [#rocdl.target] { + llvm.func @kernel() attributes {gpu.kernel, rocdl.kernel} { + llvm.return + } + } +} +''', + encoding="utf-8", + ) + + result = subprocess.run( + [ + str(_fly_opt_path()), + str(input_mlir), + "--pass-pipeline=builtin.module(gpu-module-to-binary{format=llvm})", + ], + check=False, + text=True, + capture_output=True, + ) + + assert "missing LLVMTranslationDialectInterface registration" not in result.stderr + if result.returncode != 0 and "the `AMDGPU` target was not built" in result.stderr: + return + + assert result.returncode == 0, result.stderr + assert "gpu.binary @kernels" in result.stdout diff --git a/tools/fly-opt/CMakeLists.txt b/tools/fly-opt/CMakeLists.txt index 63df13ec..a9fa94b4 100644 --- a/tools/fly-opt/CMakeLists.txt +++ b/tools/fly-opt/CMakeLists.txt @@ -6,6 +6,7 @@ set(LIBS MLIRRegisterAllExtensions MLIRMlirOptMain + MLIRToLLVMIRTranslationRegistration ) add_llvm_tool(fly-opt diff --git a/tools/fly-opt/fly-opt.cpp b/tools/fly-opt/fly-opt.cpp index fe98e38a..35d11219 100644 --- a/tools/fly-opt/fly-opt.cpp +++ b/tools/fly-opt/fly-opt.cpp @@ -9,6 +9,7 @@ #include "mlir/Pass/Pass.h" #include "mlir/Pass/PassManager.h" #include "mlir/Support/FileUtilities.h" +#include "mlir/Target/LLVMIR/Dialect/All.h" #include "mlir/Tools/mlir-opt/MlirOptMain.h" #include "mlir-c/IR.h" @@ -37,6 +38,7 @@ int main(int argc, char **argv) { mlir::DialectRegistry registry; mlir::registerAllDialects(registry); mlir::registerAllExtensions(registry); + mlir::registerAllGPUToLLVMIRTranslations(registry); registry.insert(); FOR_EACH_BACKEND(REGISTER_BACKEND_DIALECTS, FLYDSL_BACKENDS_TUPLE)