[ROCM] Validate that target triple is set in module and test for it (#24663)
Since LLVM commit
00a6186128d3 AMDGPU: Prefer getting the triple from the module over the
TargetMachine (#206055) the target riple of the module has to be set.
There was a suggestion for a dedicated test in
https://github.com/iree-org/iree/pull/24662#discussion_r3512817954.
Add the check for the target triple to the ROCM module validation and
add a LIT test for it.
This change has been assisted by Claude Code. The changes have been
reviewed manually before opening the PR.
Signed-off-by: Stefan Schuermans <schuermans@roofline.ai>
diff --git a/compiler/plugins/target/ROCM/ROCMTarget.cpp b/compiler/plugins/target/ROCM/ROCMTarget.cpp
index 32e74b8..0b1d80f 100644
--- a/compiler/plugins/target/ROCM/ROCMTarget.cpp
+++ b/compiler/plugins/target/ROCM/ROCMTarget.cpp
@@ -655,6 +655,20 @@
LogicalResult
validateFinalizedModule(IREE::HAL::ExecutableVariantOp variantOp,
llvm::Module &module, bool allowExternalDecls) {
+ // The LLVM backend reads the target triple from the module itself (not just
+ // from the TargetMachine) to decide how to emit the code object and HSA
+ // metadata. If it is left unset, code generation crashes deep inside the
+ // AMDGPU AsmPrinter with an opaque signal (a null HSAMetadataStream
+ // dereference; see llvm-project@00a6186128d3). Fail early here with an
+ // actionable message instead. The triple is set in serializeExecutable
+ // right after the data layout.
+ if (module.getTargetTriple().str().empty()) {
+ return variantOp.emitError()
+ << "the finalized LLVM module has no target triple set; it must "
+ "be set before serialization (see ROCMTargetBackend::"
+ "serializeExecutable). Without it the LLVM AMDGPU backend "
+ "crashes while emitting the object file.";
+ }
for (llvm::Function &func : module.functions()) {
if (func.isDeclaration() && !func.isIntrinsic() && !func.use_empty()) {
// In SPIR-V mode, external declarations (e.g. __ocml_*, __ockl_*,
diff --git a/compiler/plugins/target/ROCM/test/CMakeLists.txt b/compiler/plugins/target/ROCM/test/CMakeLists.txt
index 9df494d..7487c87 100644
--- a/compiler/plugins/target/ROCM/test/CMakeLists.txt
+++ b/compiler/plugins/target/ROCM/test/CMakeLists.txt
@@ -47,6 +47,7 @@
SRCS
"emit_debug_info.mlir"
"external_function_validation.mlir"
+ "module_target_triple.mlir"
"smoketest.mlir"
"smoketest_hsaco.mlir"
"target_device_features.mlir"
diff --git a/compiler/plugins/target/ROCM/test/module_target_triple.mlir b/compiler/plugins/target/ROCM/test/module_target_triple.mlir
new file mode 100644
index 0000000..5ef20c2
--- /dev/null
+++ b/compiler/plugins/target/ROCM/test/module_target_triple.mlir
@@ -0,0 +1,28 @@
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: iree-opt --iree-hal-transformation-pipeline --iree-hal-target-device=hip \
+// RUN: --iree-rocm-target=gfx942 --iree-hal-dump-executable-intermediates-to=%t %s -o /dev/null
+// RUN: cat %t/*.optimized.ll | FileCheck %s
+
+// Regression test for the target triple being set on the finalized LLVM module.
+//
+// The ROCm target backend must set the target triple of the module, because
+// the LLVM backend expects it to be set.
+// See llvm-project@00a6186128d3: ("AMDGPU: Prefer getting the triple from the
+// module over the TargetMachine").
+// Therefore, the ROCMTargetBackend validation checks for the target triple to
+// be set and emits an explicit error if that is not the case.
+
+// CHECK: target triple = "amdgcn-amd-amdhsa"
+
+#pipeline_layout = #hal.pipeline.layout<bindings = []>
+hal.executable.source public @exe {
+ hal.executable.export public @empty ordinal(0) layout(#pipeline_layout) count(%arg0: !hal.device) -> (index, index, index) {
+ %c1 = arith.constant 1 : index
+ hal.return %c1, %c1, %c1 : index, index, index
+ } attributes {subgroup_size = 64 : index, workgroup_size = [1 : index, 1 : index, 1 : index]}
+ builtin.module {
+ llvm.func @empty() attributes {rocdl.kernel} {
+ llvm.return
+ }
+ }
+}