Skip to content

Commit c4c5d7d

Browse files
committed
Update MLIR conversion to LLVMFunc to account better for properties
Change the attribute propagation to handle only discardable attributes, inherent attribute are handled directly and args/results through the interface.
1 parent 7cc1bfa commit c4c5d7d

File tree

3 files changed

+95
-95
lines changed

3 files changed

+95
-95
lines changed

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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 79 additions & 95 deletions
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

Lines changed: 15 additions & 0 deletions
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)