[Mlir-commits] [mlir] [MLIR] Account for named attributes without dialect prefixes in `FuncToLLVM` lowering pass (PR #182987)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Mon Feb 23 19:12:50 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir
Author: Ayokunle Amodu (ayokunle321)
<details>
<summary>Changes</summary>
Fixes https://github.com/llvm/llvm-project/issues/181464.
Explanation of the issue:
In `convertFuncOpToLLVMFuncOp`, the function `filterFuncAttributes` is called to remove named attributes already handled by the `FuncOp`'s build function. This is done so that the `FuncOp`'s list of named attributes does not have duplicates when trying to create a sorted dictionary out of it. In the crash-inducing test below, the named attribute `linkage` slips through the filter because it does not have its dialect prefix, i.e., it is defined as `linkage` and not `llvm.linkage` (the pass was designed to handle only dialect-prefixed attributes, but MLIR does not enforce dialect prefixed attributes). Due to this, an assert that checks for duplicates in the attribute list fails.
Minimal IR:
```
module {
func.func @<!-- -->host() attributes {linkage = #llvm.linkage<internal>} {
return
}
}
```
This patch updates the `FuncToLLVM` lowering pass to account for attribute names without dialect prefixes.
@<!-- -->matthias-springer I know the fix is funky 😔, please bare with me. Open to suggestions for a better workaround.
---
Full diff: https://github.com/llvm/llvm-project/pull/182987.diff
1 Files Affected:
- (modified) mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp (+22-7)
``````````diff
diff --git a/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp b/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp
index 2220f61ed8a07..d0b33bae6d0a5 100644
--- a/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp
+++ b/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp
@@ -52,10 +52,15 @@ static constexpr StringRef varargsAttrName = "func.varargs";
static constexpr StringRef linkageAttrName = "llvm.linkage";
static constexpr StringRef barePtrAttrName = "llvm.bareptr";
+static constexpr StringRef varargsAttrNameNoPrefix = "varargs";
+static constexpr StringRef linkageAttrNameNoPrefix = "linkage";
+static constexpr StringRef barePtrAttrNameNoPrefix = "bareptr";
+
/// Return `true` if the `op` should use bare pointer calling convention.
static bool shouldUseBarePtrCallConv(Operation *op,
const LLVMTypeConverter *typeConverter) {
- return (op && op->hasAttr(barePtrAttrName)) ||
+ return (op && (op->hasAttr(barePtrAttrName) ||
+ op->hasAttr(barePtrAttrNameNoPrefix))) ||
typeConverter->getOptions().useBarePtrCallConv;
}
@@ -65,7 +70,9 @@ static void filterFuncAttributes(FunctionOpInterface func,
SmallVectorImpl<NamedAttribute> &result) {
for (const NamedAttribute &attr : func->getDiscardableAttrs()) {
if (attr.getName() == linkageAttrName ||
+ attr.getName() == linkageAttrNameNoPrefix ||
attr.getName() == varargsAttrName ||
+ attr.getName() == varargsAttrNameNoPrefix ||
attr.getName() == LLVM::LLVMDialect::getReadnoneAttrName())
continue;
result.push_back(attr);
@@ -299,7 +306,10 @@ FailureOr<LLVM::LLVMFuncOp> mlir::convertFuncOpToLLVMFuncOp(
// Convert the original function arguments. They are converted using the
// LLVMTypeConverter provided to this legalization pattern.
- auto varargsAttr = funcOp->getAttrOfType<BoolAttr>(varargsAttrName);
+ auto varargsAttr =
+ funcOp->getAttrOfType<BoolAttr>(varargsAttrName)
+ ? funcOp->getAttrOfType<BoolAttr>(varargsAttrName)
+ : funcOp->getAttrOfType<BoolAttr>(varargsAttrNameNoPrefix);
// Gather `llvm.byval` and `llvm.byref` arguments whose type convertion was
// overriden with an LLVM pointer type for later processing.
SmallVector<std::optional<NamedAttribute>> byValRefNonPtrAttrs;
@@ -323,9 +333,12 @@ FailureOr<LLVM::LLVMFuncOp> mlir::convertFuncOpToLLVMFuncOp(
// Create an LLVM function, use external linkage by default until MLIR
// functions have linkage.
LLVM::Linkage linkage = LLVM::Linkage::External;
- if (funcOp->hasAttr(linkageAttrName)) {
- auto attr =
- dyn_cast<mlir::LLVM::LinkageAttr>(funcOp->getAttr(linkageAttrName));
+ if (funcOp->hasAttr(linkageAttrName) ||
+ funcOp->hasAttr(linkageAttrNameNoPrefix)) {
+ auto attr = dyn_cast_or_null<mlir::LLVM::LinkageAttr>(
+ funcOp->getAttr(linkageAttrName)
+ ? funcOp->getAttr(linkageAttrName)
+ : funcOp->getAttr(linkageAttrNameNoPrefix));
if (!attr) {
funcOp->emitError() << "Contains " << linkageAttrName
<< " attribute not of type LLVM::LinkageAttr";
@@ -651,13 +664,15 @@ class CallOpLowering : public CallOpInterfaceLowering<func::CallOp> {
Operation *callee =
symbolTables->lookupNearestSymbolFrom(callOp, callOp.getCalleeAttr());
useBarePtrCallConv =
- callee != nullptr && callee->hasAttr(barePtrAttrName);
+ callee != nullptr && (callee->hasAttr(barePtrAttrName) ||
+ callee->hasAttr(barePtrAttrNameNoPrefix));
} else {
// Warning: This is a linear lookup.
Operation *callee =
SymbolTable::lookupNearestSymbolFrom(callOp, callOp.getCalleeAttr());
useBarePtrCallConv =
- callee != nullptr && callee->hasAttr(barePtrAttrName);
+ callee != nullptr && (callee->hasAttr(barePtrAttrName) ||
+ callee->hasAttr(barePtrAttrNameNoPrefix));
}
return matchAndRewriteImpl(callOp, adaptor, rewriter, useBarePtrCallConv);
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/182987
More information about the Mlir-commits
mailing list