[Mlir-commits] [mlir] [mlir][func] Account for named attributes without a dialect prefix in `FuncToLLVM` lowering pass (PR #182987)
Ayokunle Amodu
llvmlistbot at llvm.org
Sat Feb 28 13:29:29 PST 2026
================
@@ -87,12 +87,3 @@ func.func @multiple_arg_attr_multiple_res_attr(%arg0: memref<f32> {test.argZero
%2 = arith.constant 2 : i32
return %0, %1, %2 : f32, memref<i32>, i32
}
-
-// CHECK: llvm.func @drop_linkage_attr() -> (!llvm.struct{{.*}} {test.returnOne})
-// CHECK-LABEL: llvm.func @_mlir_ciface_drop_linkage_attr
-// CHECK-SAME: !llvm.ptr
-// CHECK-NOT: llvm.linkage
-func.func @drop_linkage_attr() -> (memref<f32> {test.returnOne}) attributes { llvm.linkage = #llvm.linkage<external> } {
- %0 = memref.alloc() : memref<f32>
- return %0 : memref<f32>
-}
----------------
ayokunle321 wrote:
Because `getAttributeNames()` returns the raw attribute names. So if `linkage` is seen, it gets removed, but `llvm.linkage` would not.
I think why they had it hardcoded those particular names in the first place is because the build function already handles them.
If you look at the [`convertFuncOpToLLVMFuncOp`](https://github.com/llvm/llvm-project/blob/59ba10b9d38a27e6783a64f21c0a4f56bccae126/mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp#L323), it basically initializes all the attributes needed for `LLVMFuncOp::create` before the filter.
For instance, if we had `llvm.passthrough`, which is ODS-defined , we would want this to remain in the attribute list and not get filtered out. The reason why it's fine for `llvm.linkage` to get filtered out is because it's meant to be handled by the build:
```cpp
void LLVMFuncOp::build(OpBuilder &builder, OperationState &result,
StringRef name, Type type, LLVM::Linkage linkage,
bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
ArrayRef<NamedAttribute> attrs,
ArrayRef<DictionaryAttr> argAttrs,
std::optional<uint64_t> functionEntryCount) {
result.addRegion();
result.addAttribute(SymbolTable::getSymbolAttrName(),
builder.getStringAttr(name));
result.addAttribute(getFunctionTypeAttrName(result.name),
TypeAttr::get(type));
result.addAttribute(getLinkageAttrName(result.name),
LinkageAttr::get(builder.getContext(), linkage));
result.addAttribute(getCConvAttrName(result.name),
CConvAttr::get(builder.getContext(), cconv));
result.attributes.append(attrs.begin(), attrs.end());
if (dsoLocal)
result.addAttribute(getDsoLocalAttrName(result.name),
builder.getUnitAttr());
if (comdat)
result.addAttribute(getComdatAttrName(result.name), comdat);
if (functionEntryCount)
result.addAttribute(getFunctionEntryCountAttrName(result.name),
builder.getI64IntegerAttr(functionEntryCount.value()));
if (argAttrs.empty())
return;
```
So essentially, I'm thinking we still need the hardcoded filter as well as the ODS one. Because we do not want to see an attribute list with either:
sym_name
function_type
linkage
CConv
linkage
or
sym_name
function_type
linkage
CConv
llvm.linkage
but
sym_name
function_type
linkage
CConv
llvm.passthrough
would be fine.
Thoughts?
https://github.com/llvm/llvm-project/pull/182987
More information about the Mlir-commits
mailing list