Skip to content

Commit cb550c1

Browse files
authored
Update MLIR conversion to LLVMFunc to account better for properties (#67406)
Change the attribute propagation to handle only discardable attributes, inherent attribute are handled directly and args/results through the interface.
1 parent 8868431 commit cb550c1

File tree

3 files changed

+95
-95
lines changed

3 files changed

+95
-95
lines changed

mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td

+1
Original file line numberDiff line numberDiff line change
@@ -1395,6 +1395,7 @@ def LLVM_LLVMFuncOp : LLVM_Op<"func", [
13951395

13961396
let arguments = (ins
13971397
StrAttr:$sym_name,
1398+
OptionalAttr<StrAttr>:$sym_visibility,
13981399
TypeAttrOf<LLVM_FunctionType>:$function_type,
13991400
DefaultValuedAttr<Linkage, "Linkage::External">:$linkage,
14001401
UnitAttr:$dso_local,

mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp

+79-95
Original file line numberDiff line numberDiff line change
@@ -73,44 +73,40 @@ static bool shouldUseBarePtrCallConv(Operation *op,
7373
}
7474

7575
/// Only retain those attributes that are not constructed by
76-
/// `LLVMFuncOp::build`. If `filterArgAttrs` is set, also filter out argument
77-
/// attributes.
78-
static void filterFuncAttributes(func::FuncOp func, bool filterArgAndResAttrs,
76+
/// `LLVMFuncOp::build`.
77+
static void filterFuncAttributes(func::FuncOp func,
7978
SmallVectorImpl<NamedAttribute> &result) {
80-
for (const NamedAttribute &attr : func->getAttrs()) {
81-
if (attr.getName() == SymbolTable::getSymbolAttrName() ||
82-
attr.getName() == func.getFunctionTypeAttrName() ||
83-
attr.getName() == linkageAttrName ||
79+
for (const NamedAttribute &attr : func->getDiscardableAttrs()) {
80+
if (attr.getName() == linkageAttrName ||
8481
attr.getName() == varargsAttrName ||
85-
attr.getName() == LLVM::LLVMDialect::getReadnoneAttrName() ||
86-
(filterArgAndResAttrs &&
87-
(attr.getName() == func.getArgAttrsAttrName() ||
88-
attr.getName() == func.getResAttrsAttrName())))
82+
attr.getName() == LLVM::LLVMDialect::getReadnoneAttrName())
8983
continue;
9084
result.push_back(attr);
9185
}
9286
}
9387

94-
/// Adds a an empty set of argument attributes for the newly added argument in
95-
/// front of the existing ones.
96-
static void prependEmptyArgAttr(OpBuilder &builder,
97-
SmallVectorImpl<NamedAttribute> &newFuncAttrs,
98-
func::FuncOp func) {
99-
auto argAttrs = func.getArgAttrs();
100-
// Nothing to do when there were no arg attrs beforehand.
101-
if (!argAttrs)
102-
return;
103-
104-
size_t numArguments = func.getNumArguments();
105-
SmallVector<Attribute> newArgAttrs;
106-
newArgAttrs.reserve(numArguments + 1);
107-
// Insert empty dictionary for the new argument.
108-
newArgAttrs.push_back(builder.getDictionaryAttr({}));
109-
110-
llvm::append_range(newArgAttrs, *argAttrs);
111-
auto newNamedAttr = builder.getNamedAttr(func.getArgAttrsAttrName(),
112-
builder.getArrayAttr(newArgAttrs));
113-
newFuncAttrs.push_back(newNamedAttr);
88+
/// Propagate argument/results attributes.
89+
static void propagateArgResAttrs(OpBuilder &builder, bool resultStructType,
90+
func::FuncOp funcOp,
91+
LLVM::LLVMFuncOp wrapperFuncOp) {
92+
auto argAttrs = funcOp.getArgAttrs();
93+
if (!resultStructType) {
94+
if (auto resAttrs = funcOp.getAllResultAttrs())
95+
wrapperFuncOp.setAllResultAttrs(resAttrs);
96+
if (argAttrs)
97+
wrapperFuncOp.setAllArgAttrs(*argAttrs);
98+
} else {
99+
SmallVector<Attribute> argAttributes;
100+
// Only modify the argument and result attributes when the result is now
101+
// an argument.
102+
if (argAttrs) {
103+
argAttributes.push_back(builder.getDictionaryAttr({}));
104+
argAttributes.append(argAttrs->begin(), argAttrs->end());
105+
wrapperFuncOp.setAllArgAttrs(argAttributes);
106+
}
107+
}
108+
if (funcOp.getSymVisibilityAttr())
109+
wrapperFuncOp.setSymVisibility(funcOp.getSymVisibilityAttr());
114110
}
115111

116112
/// Creates an auxiliary function with pointer-to-memref-descriptor-struct
@@ -129,18 +125,14 @@ static void wrapForExternalCallers(OpBuilder &rewriter, Location loc,
129125
auto [wrapperFuncType, resultStructType] =
130126
typeConverter.convertFunctionTypeCWrapper(type);
131127

132-
SmallVector<NamedAttribute, 4> attributes;
133-
// Only modify the argument and result attributes when the result is now an
134-
// argument.
135-
if (resultStructType)
136-
prependEmptyArgAttr(rewriter, attributes, funcOp);
137-
filterFuncAttributes(
138-
funcOp, /*filterArgAndResAttrs=*/static_cast<bool>(resultStructType),
139-
attributes);
128+
SmallVector<NamedAttribute> attributes;
129+
filterFuncAttributes(funcOp, attributes);
130+
140131
auto wrapperFuncOp = rewriter.create<LLVM::LLVMFuncOp>(
141132
loc, llvm::formatv("_mlir_ciface_{0}", funcOp.getName()).str(),
142133
wrapperFuncType, LLVM::Linkage::External, /*dsoLocal=*/false,
143134
/*cconv=*/LLVM::CConv::C, /*comdat=*/nullptr, attributes);
135+
propagateArgResAttrs(rewriter, !!resultStructType, funcOp, wrapperFuncOp);
144136

145137
OpBuilder::InsertionGuard guard(rewriter);
146138
rewriter.setInsertionPointToStart(wrapperFuncOp.addEntryBlock());
@@ -199,19 +191,14 @@ static void wrapExternalFunction(OpBuilder &builder, Location loc,
199191
assert(wrapperType && "unexpected type conversion failure");
200192

201193
SmallVector<NamedAttribute, 4> attributes;
202-
// Only modify the argument and result attributes when the result is now an
203-
// argument.
204-
if (resultStructType)
205-
prependEmptyArgAttr(builder, attributes, funcOp);
206-
filterFuncAttributes(
207-
funcOp, /*filterArgAndResAttrs=*/static_cast<bool>(resultStructType),
208-
attributes);
194+
filterFuncAttributes(funcOp, attributes);
209195

210196
// Create the auxiliary function.
211197
auto wrapperFunc = builder.create<LLVM::LLVMFuncOp>(
212198
loc, llvm::formatv("_mlir_ciface_{0}", funcOp.getName()).str(),
213199
wrapperType, LLVM::Linkage::External, /*dsoLocal=*/false,
214200
/*cconv=*/LLVM::CConv::C, /*comdat=*/nullptr, attributes);
201+
propagateArgResAttrs(builder, !!resultStructType, funcOp, wrapperFunc);
215202

216203
// The wrapper that we synthetize here should only be visible in this module.
217204
newFuncOp.setLinkage(LLVM::Linkage::Private);
@@ -351,21 +338,56 @@ struct FuncOpConversionBase : public ConvertOpToLLVMPattern<func::FuncOp> {
351338
if (!llvmType)
352339
return rewriter.notifyMatchFailure(funcOp, "signature conversion failed");
353340

341+
// Create an LLVM function, use external linkage by default until MLIR
342+
// functions have linkage.
343+
LLVM::Linkage linkage = LLVM::Linkage::External;
344+
if (funcOp->hasAttr(linkageAttrName)) {
345+
auto attr =
346+
dyn_cast<mlir::LLVM::LinkageAttr>(funcOp->getAttr(linkageAttrName));
347+
if (!attr) {
348+
funcOp->emitError() << "Contains " << linkageAttrName
349+
<< " attribute not of type LLVM::LinkageAttr";
350+
return rewriter.notifyMatchFailure(
351+
funcOp, "Contains linkage attribute not of type LLVM::LinkageAttr");
352+
}
353+
linkage = attr.getLinkage();
354+
}
355+
356+
SmallVector<NamedAttribute, 4> attributes;
357+
filterFuncAttributes(funcOp, attributes);
358+
auto newFuncOp = rewriter.create<LLVM::LLVMFuncOp>(
359+
funcOp.getLoc(), funcOp.getName(), llvmType, linkage,
360+
/*dsoLocal=*/false, /*cconv=*/LLVM::CConv::C, /*comdat=*/nullptr,
361+
attributes);
362+
if (funcOp.getSymVisibilityAttr())
363+
newFuncOp.setSymVisibility(funcOp.getSymVisibilityAttr());
364+
365+
// Create a memory effect attribute corresponding to readnone.
366+
StringRef readnoneAttrName = LLVM::LLVMDialect::getReadnoneAttrName();
367+
if (funcOp->hasAttr(readnoneAttrName)) {
368+
auto attr = funcOp->getAttrOfType<UnitAttr>(readnoneAttrName);
369+
if (!attr) {
370+
funcOp->emitError() << "Contains " << readnoneAttrName
371+
<< " attribute not of type UnitAttr";
372+
return rewriter.notifyMatchFailure(
373+
funcOp, "Contains readnone attribute not of type UnitAttr");
374+
}
375+
auto memoryAttr = LLVM::MemoryEffectsAttr::get(
376+
rewriter.getContext(),
377+
{LLVM::ModRefInfo::NoModRef, LLVM::ModRefInfo::NoModRef,
378+
LLVM::ModRefInfo::NoModRef});
379+
newFuncOp.setMemoryAttr(memoryAttr);
380+
}
381+
354382
// Propagate argument/result attributes to all converted arguments/result
355383
// obtained after converting a given original argument/result.
356-
SmallVector<NamedAttribute, 4> attributes;
357-
filterFuncAttributes(funcOp, /*filterArgAndResAttrs=*/true, attributes);
358384
if (ArrayAttr resAttrDicts = funcOp.getAllResultAttrs()) {
359385
assert(!resAttrDicts.empty() && "expected array to be non-empty");
360-
auto newResAttrDicts =
361-
(funcOp.getNumResults() == 1)
362-
? resAttrDicts
363-
: rewriter.getArrayAttr(rewriter.getDictionaryAttr({}));
364-
attributes.push_back(
365-
rewriter.getNamedAttr(funcOp.getResAttrsAttrName(), newResAttrDicts));
386+
if (funcOp.getNumResults() == 1)
387+
newFuncOp.setAllResultAttrs(resAttrDicts);
366388
}
367389
if (ArrayAttr argAttrDicts = funcOp.getAllArgAttrs()) {
368-
SmallVector<Attribute, 4> newArgAttrs(
390+
SmallVector<Attribute> newArgAttrs(
369391
cast<LLVM::LLVMFunctionType>(llvmType).getNumParams());
370392
for (unsigned i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
371393
// Some LLVM IR attribute have a type attached to them. During FuncOp ->
@@ -415,48 +437,10 @@ struct FuncOpConversionBase : public ConvertOpToLLVMPattern<func::FuncOp> {
415437
newArgAttrs[mapping->inputNo + j] =
416438
DictionaryAttr::get(rewriter.getContext(), {});
417439
}
418-
attributes.push_back(rewriter.getNamedAttr(
419-
funcOp.getArgAttrsAttrName(), rewriter.getArrayAttr(newArgAttrs)));
440+
if (!newArgAttrs.empty())
441+
newFuncOp.setAllArgAttrs(rewriter.getArrayAttr(newArgAttrs));
420442
}
421443

422-
// Create an LLVM function, use external linkage by default until MLIR
423-
// functions have linkage.
424-
LLVM::Linkage linkage = LLVM::Linkage::External;
425-
if (funcOp->hasAttr(linkageAttrName)) {
426-
auto attr =
427-
dyn_cast<mlir::LLVM::LinkageAttr>(funcOp->getAttr(linkageAttrName));
428-
if (!attr) {
429-
funcOp->emitError() << "Contains " << linkageAttrName
430-
<< " attribute not of type LLVM::LinkageAttr";
431-
return rewriter.notifyMatchFailure(
432-
funcOp, "Contains linkage attribute not of type LLVM::LinkageAttr");
433-
}
434-
linkage = attr.getLinkage();
435-
}
436-
437-
// Create a memory effect attribute corresponding to readnone.
438-
StringRef readnoneAttrName = LLVM::LLVMDialect::getReadnoneAttrName();
439-
LLVM::MemoryEffectsAttr memoryAttr = {};
440-
if (funcOp->hasAttr(readnoneAttrName)) {
441-
auto attr = funcOp->getAttrOfType<UnitAttr>(readnoneAttrName);
442-
if (!attr) {
443-
funcOp->emitError() << "Contains " << readnoneAttrName
444-
<< " attribute not of type UnitAttr";
445-
return rewriter.notifyMatchFailure(
446-
funcOp, "Contains readnone attribute not of type UnitAttr");
447-
}
448-
memoryAttr = LLVM::MemoryEffectsAttr::get(rewriter.getContext(),
449-
{LLVM::ModRefInfo::NoModRef,
450-
LLVM::ModRefInfo::NoModRef,
451-
LLVM::ModRefInfo::NoModRef});
452-
}
453-
auto newFuncOp = rewriter.create<LLVM::LLVMFuncOp>(
454-
funcOp.getLoc(), funcOp.getName(), llvmType, linkage,
455-
/*dsoLocal=*/false, /*cconv=*/LLVM::CConv::C, /*comdat=*/nullptr,
456-
attributes);
457-
// If the memory attribute was created, add it to the function.
458-
if (memoryAttr)
459-
newFuncOp.setMemoryAttr(memoryAttr);
460444
rewriter.inlineRegionBefore(funcOp.getBody(), newFuncOp.getBody(),
461445
newFuncOp.end());
462446
if (failed(rewriter.convertRegionTypes(&newFuncOp.getBody(), *typeConverter,

mlir/test/Conversion/FuncToLLVM/convert-funcs.mlir

+15
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,21 @@ func.func @variadic_func(%arg0: i32) attributes { "func.varargs" = true } {
6363

6464
// -----
6565

66+
// CHECK-LABEL: llvm.func @private_callee
67+
// CHECK-SAME: sym_visibility = "private"
68+
func.func private @private_callee(%arg1: f32) -> i32 {
69+
%0 = arith.constant 0 : i32
70+
return %0 : i32
71+
}
72+
73+
// CHECK-LABEL: llvm.func @caller_private_callee
74+
func.func @caller_private_callee(%arg1: f32) -> i32 {
75+
%0 = call @private_callee(%arg1) : (f32) -> i32
76+
return %0 : i32
77+
}
78+
79+
// -----
80+
6681
func.func private @badllvmlinkage(i32) attributes { "llvm.linkage" = 3 : i64 } // expected-error {{Contains llvm.linkage attribute not of type LLVM::LinkageAttr}}
6782

6883
// -----

0 commit comments

Comments
 (0)