[Mlir-commits] [mlir] [mlir][LLVMIR] Require active insertion point for llvm.call translation (PR #222920)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Fri Sep 11 04:06:43 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir-llvm
Author: Akun (AkunCube)
<details>
<summary>Changes</summary>
When a `gpu.barrier` is placed directly at the top level of a `gpu.module` (not inside a `gpu.func`), the XeVM/SPIR-V lowering pipeline rewrites itinto an `llvm.call @<!-- -->_Z7barrierj` at module scope. During LLVM IR translation, `translateModuleToLLVMIR` converts this top-level call with an `IRBuilder` that has no active insertion point. `builder.CreateCall` then produces a parentless `CallInst` that is not attached to any basic block, so when the `llvm::Module` is destroyed the callee function is freed while the dangling call still uses it, tripping "Uses remain when a value is destroyed!" in `llvm::Value::~Value()` and aborting.
Add the same guard that was introduced for the NVVM dialect in #<!-- -->188735 (fixing #<!-- -->186642): bail out with a proper MLIR diagnostic when an `llvm.call` has no active insertion point (e.g. it is misplaced at module scope) instead of leaving dangling LLVM IR that crashes during module teardown.
---
Full diff: https://github.com/llvm/llvm-project/pull/222920.diff
2 Files Affected:
- (modified) mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp (+8)
- (modified) mlir/test/Target/LLVMIR/llvmir-invalid.mlir (+10)
``````````diff
diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
index 0c715da6ba954..1bb08e8bf6fed 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
@@ -442,6 +442,14 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
// itself. Otherwise, this is an indirect call and the callee is the first
// operand, look it up as a normal value.
if (auto callOp = dyn_cast<LLVM::CallOp>(opInst)) {
+ // A null insert block means the op is misplaced (e.g., at module scope),
+ // which would otherwise leave a parentless CallInst that crashes the
+ // llvm::Module destructor ("Uses remain when a value is destroyed").
+ if (!builder.GetInsertBlock())
+ return opInst.emitOpError(
+ "cannot be translated to LLVM IR without an active insertion "
+ "point; make sure the op is inside a function");
+
auto operands = moduleTranslation.lookupValues(callOp.getCalleeOperands());
SmallVector<llvm::OperandBundleDef> opBundles =
convertOperandBundles(callOp.getOpBundleOperands(),
diff --git a/mlir/test/Target/LLVMIR/llvmir-invalid.mlir b/mlir/test/Target/LLVMIR/llvmir-invalid.mlir
index 6e8301bb626e3..dfef2bf845ebc 100644
--- a/mlir/test/Target/LLVMIR/llvmir-invalid.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir-invalid.mlir
@@ -429,3 +429,13 @@ llvm.func @invoke_branch_weights() -> i32 attributes {personality = @__gxx_perso
^bb2: // 2 preds: ^bb0, ^bb1
llvm.return %0 : i32
}
+
+// -----
+
+// Test that llvm.call at module scope (outside any function) produces a proper
+// error instead of leaving a parentless CallInst that crashes the module
+// destructor during LLVM IR translation.
+llvm.func @barrier()
+// expected-error @+2 {{'llvm.call' op cannot be translated to LLVM IR without an active insertion point}}
+// expected-error @+1 {{LLVM Translation failed for operation: llvm.call}}
+llvm.call @barrier() : () -> ()
``````````
</details>
https://github.com/llvm/llvm-project/pull/222920
More information about the Mlir-commits
mailing list