[Mlir-commits] [mlir] [MLIR][NVVM] Fix segfault when translating NVVM ops outside a function (PR #188735)

Mehdi Amini llvmlistbot at llvm.org
Thu Mar 26 05:41:29 PDT 2026


https://github.com/joker-eph created https://github.com/llvm/llvm-project/pull/188735

When a GPU barrier op was placed at the top level of a gpu.module (not inside a gpu.func), the pass pipeline lowered it to nvvm.barrier0 at module scope. During LLVM IR translation, translateModuleToLLVMIR called NVVMDialectLLVMIRTranslationInterface::convertOperation for the misplaced op, which reached createIntrinsicCall with an IRBuilder that had no active insertion point (null GetInsertBlock()), causing a null dereference crash.

The fix adds a guard at the top of the NVVM translation interface's convertOperation: all NVVM ops are instruction-level and require an active insertion point. If the insert block is null, the op must be misplaced, so we return a proper MLIR error instead of crashing.

Fixes #186642

Assisted-by: Claude Code

>From 8a2f74d77f99be7d6a9918f0e0b125902470601c Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Thu, 26 Mar 2026 05:38:44 -0700
Subject: [PATCH] [MLIR][NVVM] Fix segfault when translating NVVM ops outside a
 function

When a GPU barrier op was placed at the top level of a gpu.module (not
inside a gpu.func), the pass pipeline lowered it to nvvm.barrier0 at
module scope. During LLVM IR translation, translateModuleToLLVMIR called
NVVMDialectLLVMIRTranslationInterface::convertOperation for the misplaced
op, which reached createIntrinsicCall with an IRBuilder that had no active
insertion point (null GetInsertBlock()), causing a null dereference crash.

The fix adds a guard at the top of the NVVM translation interface's
convertOperation: all NVVM ops are instruction-level and require an active
insertion point. If the insert block is null, the op must be misplaced, so
we return a proper MLIR error instead of crashing.

Fixes https://github.com/llvm/llvm-project/issues/186642

Assisted-by: Claude Code
---
 .../LLVMIR/Dialect/NVVM/NVVMToLLVMIRTranslation.cpp   |  7 +++++++
 mlir/test/Target/LLVMIR/nvvmir-invalid.mlir           | 11 ++++++++++-
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/mlir/lib/Target/LLVMIR/Dialect/NVVM/NVVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/NVVM/NVVMToLLVMIRTranslation.cpp
index 18d42e9577095..254be8e63590f 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/NVVM/NVVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/NVVM/NVVMToLLVMIRTranslation.cpp
@@ -692,6 +692,13 @@ class NVVMDialectLLVMIRTranslationInterface
   LogicalResult
   convertOperation(Operation *op, llvm::IRBuilderBase &builder,
                    LLVM::ModuleTranslation &moduleTranslation) const final {
+    // All NVVM ops are instruction-level and require an active insertion point.
+    // A null insert block means the op is misplaced (e.g., at module scope),
+    // which would otherwise cause a null dereference in createIntrinsicCall.
+    if (!builder.GetInsertBlock())
+      return op->emitOpError(
+          "cannot be translated to LLVM IR without an active insertion "
+          "point; make sure the op is inside a function");
     Operation &opInst = *op;
 #include "mlir/Dialect/LLVMIR/NVVMConversions.inc"
 
diff --git a/mlir/test/Target/LLVMIR/nvvmir-invalid.mlir b/mlir/test/Target/LLVMIR/nvvmir-invalid.mlir
index c0fe0fa11f497..785f59b22801f 100644
--- a/mlir/test/Target/LLVMIR/nvvmir-invalid.mlir
+++ b/mlir/test/Target/LLVMIR/nvvmir-invalid.mlir
@@ -595,7 +595,7 @@ func.func @invalid_range_equal_bounds() {
 
 // -----
 
-// Test for correct return type check for wmma.load fragment a for f64 
+// Test for correct return type check for wmma.load fragment a for f64
 llvm.func @nvvm_wmma_load_a_f64(%arg0: !llvm.ptr, %arg1 : i32) {
   // expected-error @below {{'nvvm.wmma.load' op expected destination type to be f64}}
   %0 = nvvm.wmma.load %arg0, %arg1
@@ -603,3 +603,12 @@ llvm.func @nvvm_wmma_load_a_f64(%arg0: !llvm.ptr, %arg1 : i32) {
     : (!llvm.ptr) -> !llvm.struct<(f64)>
   llvm.return
 }
+
+// -----
+
+// Test that nvvm.barrier0 at module scope (outside any function) produces a
+// proper error instead of crashing with a null dereference in
+// createIntrinsicCall. See https://github.com/llvm/llvm-project/issues/186642
+// expected-error @+2 {{'nvvm.barrier0' op cannot be translated to LLVM IR without an active insertion point}}
+// expected-error @+1 {{LLVM Translation failed for operation: nvvm.barrier0}}
+nvvm.barrier0



More information about the Mlir-commits mailing list