[Mlir-commits] [mlir] 29016d2 - [mlir][llvmir] Translate function result attributes to LLVM IR.
Slava Zakharin
llvmlistbot at llvm.org
Fri Nov 18 12:03:56 PST 2022
Author: Slava Zakharin
Date: 2022-11-18T12:03:42-08:00
New Revision: 29016d2830d455cdf34a5cdf7ed63f3c3b93d9a3
URL: https://github.com/llvm/llvm-project/commit/29016d2830d455cdf34a5cdf7ed63f3c3b93d9a3
DIFF: https://github.com/llvm/llvm-project/commit/29016d2830d455cdf34a5cdf7ed63f3c3b93d9a3.diff
LOG: [mlir][llvmir] Translate function result attributes to LLVM IR.
Translate align, noalias, noundef, signext and zeroext result
attributes from llvm.func to LLVM IR.
This is needed for https://github.com/llvm/llvm-project/issues/58579
Differential Revision: https://reviews.llvm.org/D137049
Added:
Modified:
mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
mlir/test/Dialect/LLVMIR/func.mlir
mlir/test/Target/LLVMIR/llvmir.mlir
Removed:
################################################################################
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index c2b09619a5f52..f9264d5d60154 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -2152,14 +2152,6 @@ LogicalResult LLVMFuncOp::verify() {
<< stringifyLinkage(LLVM::Linkage::Common)
<< "' linkage";
- // Check to see if this function has a void return with a result attribute to
- // it. It isn't clear what semantics we would assign to that.
- if (getFunctionType().getReturnType().isa<LLVMVoidType>() &&
- !getResultAttrs(0).empty()) {
- return emitOpError()
- << "cannot attach result attributes to functions with a void return";
- }
-
if (isExternal()) {
if (getLinkage() != LLVM::Linkage::External &&
getLinkage() != LLVM::Linkage::ExternWeak)
@@ -2777,12 +2769,75 @@ LogicalResult LLVMDialect::verifyRegionResultAttribute(Operation *op,
unsigned regionIdx,
unsigned resIdx,
NamedAttribute resAttr) {
- if (resAttr.getName() == LLVMDialect::getStructAttrsAttrName()) {
+ StringAttr name = resAttr.getName();
+ if (name == LLVMDialect::getStructAttrsAttrName()) {
return verifyFuncOpInterfaceStructAttr(
op, resAttr.getValue(), [resIdx](FunctionOpInterface funcOp) {
return funcOp.getResultTypes()[resIdx];
});
}
+ if (auto funcOp = dyn_cast<FunctionOpInterface>(op)) {
+ mlir::Type resTy = funcOp.getResultTypes()[resIdx];
+
+ // Check to see if this function has a void return with a result attribute
+ // to it. It isn't clear what semantics we would assign to that.
+ if (resTy.isa<LLVMVoidType>())
+ return op->emitError() << "cannot attach result attributes to functions "
+ "with a void return";
+
+ // LLVM attribute may be attached to a result of operation
+ // that has not been converted to LLVM dialect yet, so the result
+ // may have a type with unknown representation in LLVM dialect type
+ // space. In this case we cannot verify whether the attribute may be
+ // attached to a result of such type.
+ bool verifyValueType = isCompatibleType(resTy);
+ Attribute attrValue = resAttr.getValue();
+
+ // TODO: get rid of code duplication here and in verifyRegionArgAttribute().
+ if (name == LLVMDialect::getAlignAttrName()) {
+ if (!attrValue.isa<IntegerAttr>())
+ return op->emitError() << "expected llvm.align result attribute to be "
+ "an integer attribute";
+ if (verifyValueType && !resTy.isa<LLVMPointerType>())
+ return op->emitError()
+ << "llvm.align attribute attached to non-pointer result";
+ return success();
+ }
+ if (name == LLVMDialect::getNoAliasAttrName()) {
+ if (!attrValue.isa<UnitAttr>())
+ return op->emitError() << "expected llvm.noalias result attribute to "
+ "be a unit attribute";
+ if (verifyValueType && !resTy.isa<LLVMPointerType>())
+ return op->emitError()
+ << "llvm.noalias attribute attached to non-pointer result";
+ return success();
+ }
+ if (name == LLVMDialect::getNoUndefAttrName()) {
+ if (!attrValue.isa<UnitAttr>())
+ return op->emitError() << "expected llvm.noundef result attribute to "
+ "be a unit attribute";
+ return success();
+ }
+ if (name == LLVMDialect::getSExtAttrName()) {
+ if (!attrValue.isa<UnitAttr>())
+ return op->emitError() << "expected llvm.signext result attribute to "
+ "be a unit attribute";
+ if (verifyValueType && !resTy.isa<mlir::IntegerType>())
+ return op->emitError()
+ << "llvm.signext attribute attached to non-integer result";
+ return success();
+ }
+ if (name == LLVMDialect::getZExtAttrName()) {
+ if (!attrValue.isa<UnitAttr>())
+ return op->emitError() << "expected llvm.zeroext result attribute to "
+ "be a unit attribute";
+ if (verifyValueType && !resTy.isa<mlir::IntegerType>())
+ return op->emitError()
+ << "llvm.zeroext attribute attached to non-integer result";
+ return success();
+ }
+ }
+
return success();
}
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 7c0e3efe8e0b6..a398002bd1046 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -885,9 +885,32 @@ LogicalResult ModuleTranslation::convertFunctionSignatures() {
mapFunction(function.getName(), llvmFunc);
addRuntimePreemptionSpecifier(function.getDsoLocal(), llvmFunc);
+ // Convert function attributes.
if (function->getAttrOfType<UnitAttr>(LLVMDialect::getReadnoneAttrName()))
llvmFunc->setDoesNotAccessMemory();
+ // Convert result attributes.
+ if (ArrayAttr allResultAttrs = function.getAllResultAttrs()) {
+ llvm::AttrBuilder retAttrs(llvmFunc->getContext());
+ DictionaryAttr resultAttrs = allResultAttrs[0].cast<DictionaryAttr>();
+ for (const NamedAttribute &attr : resultAttrs) {
+ StringAttr name = attr.getName();
+ if (name == LLVMDialect::getAlignAttrName()) {
+ auto alignAmount = attr.getValue().cast<IntegerAttr>();
+ retAttrs.addAlignmentAttr(llvm::Align(alignAmount.getInt()));
+ } else if (name == LLVMDialect::getNoAliasAttrName()) {
+ retAttrs.addAttribute(llvm::Attribute::NoAlias);
+ } else if (name == LLVMDialect::getNoUndefAttrName()) {
+ retAttrs.addAttribute(llvm::Attribute::NoUndef);
+ } else if (name == LLVMDialect::getSExtAttrName()) {
+ retAttrs.addAttribute(llvm::Attribute::SExt);
+ } else if (name == LLVMDialect::getZExtAttrName()) {
+ retAttrs.addAttribute(llvm::Attribute::ZExt);
+ }
+ }
+ llvmFunc->addRetAttrs(retAttrs);
+ }
+
// Convert argument attributes.
unsigned int argIdx = 0;
for (auto [mlirArgTy, llvmArg] :
diff --git a/mlir/test/Dialect/LLVMIR/func.mlir b/mlir/test/Dialect/LLVMIR/func.mlir
index 7746d5c04b811..8f347598bd7cf 100644
--- a/mlir/test/Dialect/LLVMIR/func.mlir
+++ b/mlir/test/Dialect/LLVMIR/func.mlir
@@ -257,11 +257,56 @@ module {
module {
// expected-error at +1 {{cannot attach result attributes to functions with a void return}}
- llvm.func @variadic_def() -> (!llvm.void {llvm.noalias})
+ llvm.func @variadic_def() -> (!llvm.void {llvm.noundef})
}
// -----
+// expected-error @below{{expected llvm.align result attribute to be an integer attribute}}
+llvm.func @alignattr_ret() -> (!llvm.ptr {llvm.align = 1.0 : f32})
+
+// -----
+
+// expected-error @below{{llvm.align attribute attached to non-pointer result}}
+llvm.func @alignattr_ret() -> (i32 {llvm.align = 4})
+
+// -----
+
+// expected-error @below{{expected llvm.noalias result attribute to be a unit attribute}}
+llvm.func @noaliasattr_ret() -> (!llvm.ptr {llvm.noalias = 1})
+
+// -----
+
+// expected-error @below{{llvm.noalias attribute attached to non-pointer result}}
+llvm.func @noaliasattr_ret() -> (i32 {llvm.noalias})
+
+// -----
+
+// expected-error @below{{expected llvm.noundef result attribute to be a unit attribute}}
+llvm.func @noundefattr_ret() -> (!llvm.ptr {llvm.noundef = 1})
+
+// -----
+
+// expected-error @below{{expected llvm.signext result attribute to be a unit attribute}}
+llvm.func @signextattr_ret() -> (i32 {llvm.signext = 1})
+
+// -----
+
+// expected-error @below{{llvm.signext attribute attached to non-integer result}}
+llvm.func @signextattr_ret() -> (f32 {llvm.signext})
+
+// -----
+
+// expected-error @below{{expected llvm.zeroext result attribute to be a unit attribute}}
+llvm.func @zeroextattr_ret() -> (i32 {llvm.zeroext = 1})
+
+// -----
+
+// expected-error @below{{llvm.zeroext attribute attached to non-integer result}}
+llvm.func @zeroextattr_ret() -> (f32 {llvm.zeroext})
+
+// -----
+
module {
// expected-error at +1 {{variadic arguments must be in the end of the argument list}}
llvm.func @variadic_inside(%arg0: i32, ..., %arg1: i32)
diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir
index 0ca8bb02c2bb1..f9733157f1a87 100644
--- a/mlir/test/Target/LLVMIR/llvmir.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir.mlir
@@ -1124,6 +1124,17 @@ llvm.func @zeroextattr(%arg0: i1 {llvm.zeroext}) {
// CHECK-LABEL: declare void @zeroextattr_decl(i1 zeroext)
llvm.func @zeroextattr_decl(i1 {llvm.zeroext})
+// CHECK-LABEL: declare align 4 ptr @alignattr_ret_decl()
+llvm.func @alignattr_ret_decl() -> (!llvm.ptr<i32> {llvm.align = 4})
+// CHECK-LABEL: declare noalias ptr @noaliasattr_ret_decl()
+llvm.func @noaliasattr_ret_decl() -> (!llvm.ptr<i32> {llvm.noalias})
+// CHECK-LABEL: declare noundef ptr @noundefattr_ret_decl()
+llvm.func @noundefattr_ret_decl() -> (!llvm.ptr<i32> {llvm.noundef})
+// CHECK-LABEL: declare signext i1 @signextattr_ret_decl()
+llvm.func @signextattr_ret_decl() -> (i1 {llvm.signext})
+// CHECK-LABEL: declare zeroext i1 @zeroextattr_ret_decl()
+llvm.func @zeroextattr_ret_decl() -> (i1 {llvm.zeroext})
+
// CHECK-LABEL: @llvm_varargs(...)
llvm.func @llvm_varargs(...)
More information about the Mlir-commits
mailing list