[Mlir-commits] [mlir] 5212058 - Reland "[mlir][LLVM] Add all LLVM parameter attributes"
Christian Ulmann
llvmlistbot at llvm.org
Tue Jan 31 00:12:02 PST 2023
Author: Christian Ulmann
Date: 2023-01-31T09:11:02+01:00
New Revision: 5212058405ba9ed1292920f075c2ae06f67cc5f7
URL: https://github.com/llvm/llvm-project/commit/5212058405ba9ed1292920f075c2ae06f67cc5f7
DIFF: https://github.com/llvm/llvm-project/commit/5212058405ba9ed1292920f075c2ae06f67cc5f7.diff
LOG: Reland "[mlir][LLVM] Add all LLVM parameter attributes"
This change was reverted because it introduced a linking issue due to
duplicated symbols. Making sure that the detail helper only has a static
header implementation fixes this issue.
Reviewed By: gysit
Differential Revision: https://reviews.llvm.org/D142635
Added:
mlir/lib/Target/LLVMIR/AttrKindDetail.h
Modified:
mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
mlir/lib/Target/LLVMIR/ModuleImport.cpp
mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
mlir/test/Dialect/LLVMIR/parameter-attrs-invalid.mlir
mlir/test/Target/LLVMIR/Import/function-attributes.ll
mlir/test/Target/LLVMIR/llvmir.mlir
Removed:
################################################################################
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
index 9166ae78bd113..3f99dcbcccaa0 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
@@ -36,9 +36,6 @@ def LLVM_Dialect : Dialect {
let extraClassDeclaration = [{
/// Name of the data layout attributes.
static StringRef getDataLayoutAttrName() { return "llvm.data_layout"; }
- static StringRef getAlignAttrName() { return "llvm.align"; }
- static StringRef getNoAliasAttrName() { return "llvm.noalias"; }
- static StringRef getReadonlyAttrName() { return "llvm.readonly"; }
static StringRef getNoAliasScopesAttrName() { return "noalias_scopes"; }
static StringRef getAliasScopesAttrName() { return "alias_scopes"; }
static StringRef getLoopAttrName() { return "llvm.loop"; }
@@ -46,15 +43,37 @@ def LLVM_Dialect : Dialect {
static StringRef getLoopOptionsAttrName() { return "options"; }
static StringRef getAccessGroupsAttrName() { return "access_groups"; }
static StringRef getStructAttrsAttrName() { return "llvm.struct_attrs"; }
+ static StringRef getTBAAAttrName() { return "llvm.tbaa"; }
+
+ /// Names of llvm parameter attributes.
+ static StringRef getAlignAttrName() { return "llvm.align"; }
+ static StringRef getAllocAlignAttrName() { return "llvm.allocalign"; }
+ static StringRef getAllocatedPointerAttrName() { return "llvm.allocptr"; }
static StringRef getByValAttrName() { return "llvm.byval"; }
static StringRef getByRefAttrName() { return "llvm.byref"; }
- static StringRef getStructRetAttrName() { return "llvm.sret"; }
- static StringRef getInAllocaAttrName() { return "llvm.inalloca"; }
static StringRef getNoUndefAttrName() { return "llvm.noundef"; }
+ static StringRef getDereferenceableAttrName() { return "llvm.dereferenceable"; }
+ static StringRef getDereferenceableOrNullAttrName() { return "llvm.dereferenceable_or_null"; }
+ static StringRef getInAllocaAttrName() { return "llvm.inalloca"; }
+ static StringRef getInRegAttrName() { return "llvm.inreg"; }
+ static StringRef getNestAttrName() { return "llvm.nest"; }
+ static StringRef getNoAliasAttrName() { return "llvm.noalias"; }
+ static StringRef getNoCaptureAttrName() { return "llvm.nocapture"; }
+ static StringRef getNoFreeAttrName() { return "llvm.nofree"; }
+ static StringRef getNonNullAttrName() { return "llvm.nonnull"; }
+ static StringRef getPreallocatedAttrName() { return "llvm.preallocated"; }
+ static StringRef getReadonlyAttrName() { return "llvm.readonly"; }
+ static StringRef getReturnedAttrName() { return "llvm.returned"; }
static StringRef getSExtAttrName() { return "llvm.signext"; }
+ static StringRef getStackAlignmentAttrName() { return "llvm.alignstack"; }
+ static StringRef getStructRetAttrName() { return "llvm.sret"; }
+ static StringRef getWriteOnlyAttrName() { return "llvm.writeonly"; }
static StringRef getZExtAttrName() { return "llvm.zeroext"; }
- static StringRef getTBAAAttrName() { return "llvm.tbaa"; }
- static StringRef getNestAttrName() { return "llvm.nest"; }
+ // TODO Restrict the usage of this to parameter attributes once there is an
+ // alternative way of modeling memory effects on FunctionOpInterface.
+ /// Name of the attribute that will cause the creation of a readnone memory
+ /// effect when lowering to the LLVMDialect.
+ static StringRef getReadnoneAttrName() { return "llvm.readnone"; }
/// Verifies if the attribute is a well-formed value for "llvm.struct_attrs"
static LogicalResult verifyStructAttr(
@@ -76,13 +95,6 @@ def LLVM_Dialect : Dialect {
/// Returns `true` if the given type is compatible with the LLVM dialect.
static bool isCompatibleType(Type);
- /// TODO Remove this once there is an alternative way of modeling memory
- /// effects on FunctionOpInterface.
- /// Name of the attribute that will cause the creation of a readnone memory
- /// effect when lowering to the LLVMDialect.
- static StringRef getReadnoneAttrName() {
- return "llvm.readnone";
- }
Type parseType(DialectAsmParser &p) const override;
void printType(Type, DialectAsmPrinter &p) const override;
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 1940bcda7b619..8e925714c039b 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -3274,7 +3274,12 @@ LogicalResult LLVMDialect::verifyParameterAttribute(Operation *op,
// Check a unit attribute that is attached to a pointer value.
if (name == LLVMDialect::getNoAliasAttrName() ||
name == LLVMDialect::getReadonlyAttrName() ||
- name == LLVMDialect::getNestAttrName()) {
+ name == LLVMDialect::getReadnoneAttrName() ||
+ name == LLVMDialect::getWriteOnlyAttrName() ||
+ name == LLVMDialect::getNestAttrName() ||
+ name == LLVMDialect::getNoCaptureAttrName() ||
+ name == LLVMDialect::getNoFreeAttrName() ||
+ name == LLVMDialect::getNonNullAttrName()) {
if (failed(checkUnitAttrType()))
return failure();
if (verifyValueType && failed(checkPointerType()))
@@ -3286,7 +3291,8 @@ LogicalResult LLVMDialect::verifyParameterAttribute(Operation *op,
if (name == LLVMDialect::getStructRetAttrName() ||
name == LLVMDialect::getByValAttrName() ||
name == LLVMDialect::getByRefAttrName() ||
- name == LLVMDialect::getInAllocaAttrName()) {
+ name == LLVMDialect::getInAllocaAttrName() ||
+ name == LLVMDialect::getPreallocatedAttrName()) {
if (failed(checkTypeAttrType()))
return failure();
if (verifyValueType && failed(checkPointerTypeMatches()))
@@ -3305,7 +3311,10 @@ LogicalResult LLVMDialect::verifyParameterAttribute(Operation *op,
}
// Check an integer attribute that is attached to a pointer value.
- if (name == LLVMDialect::getAlignAttrName()) {
+ if (name == LLVMDialect::getAlignAttrName() ||
+ name == LLVMDialect::getDereferenceableAttrName() ||
+ name == LLVMDialect::getDereferenceableOrNullAttrName() ||
+ name == LLVMDialect::getStackAlignmentAttrName()) {
if (failed(checkIntegerAttrType()))
return failure();
if (verifyValueType && failed(checkPointerType()))
@@ -3313,8 +3322,12 @@ LogicalResult LLVMDialect::verifyParameterAttribute(Operation *op,
return success();
}
- if (name == LLVMDialect::getNoUndefAttrName())
+ // Check a unit attribute that can be attached to arbitrary types.
+ if (name == LLVMDialect::getNoUndefAttrName() ||
+ name == LLVMDialect::getInRegAttrName() ||
+ name == LLVMDialect::getReturnedAttrName())
return checkUnitAttrType();
+
return success();
}
@@ -3349,12 +3362,21 @@ LogicalResult LLVMDialect::verifyRegionResultAttribute(Operation *op,
// Check to see if this attribute is allowed as a result attribute. Only
// explicitly forbidden LLVM attributes will cause an error.
auto name = resAttr.getName();
- if (name == LLVMDialect::getReadonlyAttrName() ||
- name == LLVMDialect::getNestAttrName() ||
- name == LLVMDialect::getStructRetAttrName() ||
+ if (name == LLVMDialect::getAllocAlignAttrName() ||
+ name == LLVMDialect::getAllocatedPointerAttrName() ||
name == LLVMDialect::getByValAttrName() ||
name == LLVMDialect::getByRefAttrName() ||
- name == LLVMDialect::getInAllocaAttrName())
+ name == LLVMDialect::getInAllocaAttrName() ||
+ name == LLVMDialect::getNestAttrName() ||
+ name == LLVMDialect::getNoCaptureAttrName() ||
+ name == LLVMDialect::getNoFreeAttrName() ||
+ name == LLVMDialect::getPreallocatedAttrName() ||
+ name == LLVMDialect::getReadnoneAttrName() ||
+ name == LLVMDialect::getReadonlyAttrName() ||
+ name == LLVMDialect::getReturnedAttrName() ||
+ name == LLVMDialect::getStackAlignmentAttrName() ||
+ name == LLVMDialect::getStructRetAttrName() ||
+ name == LLVMDialect::getWriteOnlyAttrName())
return op->emitError() << name << " is not a valid result attribute";
return verifyParameterAttribute(op, resType, resAttr);
}
diff --git a/mlir/lib/Target/LLVMIR/AttrKindDetail.h b/mlir/lib/Target/LLVMIR/AttrKindDetail.h
new file mode 100644
index 0000000000000..7f81777886f56
--- /dev/null
+++ b/mlir/lib/Target/LLVMIR/AttrKindDetail.h
@@ -0,0 +1,66 @@
+//===- AttrKindDetail.h - AttrKind conversion details -----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ATTRKINDDETAIL_H_
+#define ATTRKINDDETAIL_H_
+
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "llvm/IR/Attributes.h"
+
+namespace mlir {
+namespace LLVM {
+namespace detail {
+
+/// Returns a list of pairs that each hold a mapping from LLVM attribute kinds
+/// to their corresponding string name in LLVM IR dialect.
+static llvm::ArrayRef<std::pair<llvm::Attribute::AttrKind, llvm::StringRef>>
+getAttrKindToNameMapping() {
+ using ElemTy = std::pair<llvm::Attribute::AttrKind, llvm::StringRef>;
+ // Mapping from llvm attribute kinds to their corresponding MLIR name.
+ static const llvm::SmallVector<ElemTy> kindNamePairs = {
+ {llvm::Attribute::AttrKind::Alignment, LLVMDialect::getAlignAttrName()},
+ {llvm::Attribute::AttrKind::AllocAlign,
+ LLVMDialect::getAllocAlignAttrName()},
+ {llvm::Attribute::AttrKind::AllocatedPointer,
+ LLVMDialect::getAllocatedPointerAttrName()},
+ {llvm::Attribute::AttrKind::ByVal, LLVMDialect::getByValAttrName()},
+ {llvm::Attribute::AttrKind::ByRef, LLVMDialect::getByRefAttrName()},
+ {llvm::Attribute::AttrKind::NoUndef, LLVMDialect::getNoUndefAttrName()},
+ {llvm::Attribute::AttrKind::Dereferenceable,
+ LLVMDialect::getDereferenceableAttrName()},
+ {llvm::Attribute::AttrKind::DereferenceableOrNull,
+ LLVMDialect::getDereferenceableOrNullAttrName()},
+ {llvm::Attribute::AttrKind::InAlloca, LLVMDialect::getInAllocaAttrName()},
+ {llvm::Attribute::AttrKind::InReg, LLVMDialect::getInRegAttrName()},
+ {llvm::Attribute::AttrKind::Nest, LLVMDialect::getNestAttrName()},
+ {llvm::Attribute::AttrKind::NoAlias, LLVMDialect::getNoAliasAttrName()},
+ {llvm::Attribute::AttrKind::NoCapture,
+ LLVMDialect::getNoCaptureAttrName()},
+ {llvm::Attribute::AttrKind::NoFree, LLVMDialect::getNoFreeAttrName()},
+ {llvm::Attribute::AttrKind::NonNull, LLVMDialect::getNonNullAttrName()},
+ {llvm::Attribute::AttrKind::Preallocated,
+ LLVMDialect::getPreallocatedAttrName()},
+ {llvm::Attribute::AttrKind::ReadOnly, LLVMDialect::getReadonlyAttrName()},
+ {llvm::Attribute::AttrKind::ReadNone, LLVMDialect::getReadnoneAttrName()},
+ {llvm::Attribute::AttrKind::Returned, LLVMDialect::getReturnedAttrName()},
+ {llvm::Attribute::AttrKind::SExt, LLVMDialect::getSExtAttrName()},
+ {llvm::Attribute::AttrKind::StackAlignment,
+ LLVMDialect::getStackAlignmentAttrName()},
+ {llvm::Attribute::AttrKind::StructRet,
+ LLVMDialect::getStructRetAttrName()},
+ {llvm::Attribute::AttrKind::WriteOnly,
+ LLVMDialect::getWriteOnlyAttrName()},
+ {llvm::Attribute::AttrKind::ZExt, LLVMDialect::getZExtAttrName()}};
+ return kindNamePairs;
+}
+
+} // namespace detail
+} // namespace LLVM
+} // namespace mlir
+
+#endif // ATTRKINDDETAIL_H_
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 1c736614d44f7..fb0825bed3fa2 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -14,6 +14,7 @@
#include "mlir/Target/LLVMIR/ModuleImport.h"
#include "mlir/Target/LLVMIR/Import.h"
+#include "AttrKindDetail.h"
#include "DebugImporter.h"
#include "mlir/Dialect/DLTI/DLTI.h"
@@ -1536,24 +1537,8 @@ void ModuleImport::processFunctionAttributes(llvm::Function *func,
DictionaryAttr
ModuleImport::convertParameterAttribute(llvm::AttributeSet llvmParamAttrs,
OpBuilder &builder) {
- using ElemTy = std::pair<llvm::Attribute::AttrKind, StringRef>;
- // Mapping from llvm attribute kinds to their corresponding MLIR name.
- static const SmallVector<ElemTy> kindNamePairs = {
- {llvm::Attribute::AttrKind::NoAlias, LLVMDialect::getNoAliasAttrName()},
- {llvm::Attribute::AttrKind::ReadOnly, LLVMDialect::getReadonlyAttrName()},
- {llvm::Attribute::AttrKind::Nest, LLVMDialect::getNestAttrName()},
- {llvm::Attribute::AttrKind::SExt, LLVMDialect::getSExtAttrName()},
- {llvm::Attribute::AttrKind::ZExt, LLVMDialect::getZExtAttrName()},
- {llvm::Attribute::AttrKind::NoUndef, LLVMDialect::getNoUndefAttrName()},
- {llvm::Attribute::AttrKind::StructRet,
- LLVMDialect::getStructRetAttrName()},
- {llvm::Attribute::AttrKind::ByVal, LLVMDialect::getByValAttrName()},
- {llvm::Attribute::AttrKind::ByRef, LLVMDialect::getByRefAttrName()},
- {llvm::Attribute::AttrKind::InAlloca, LLVMDialect::getInAllocaAttrName()},
- {llvm::Attribute::AttrKind::Alignment, LLVMDialect::getAlignAttrName()}};
-
SmallVector<NamedAttribute> paramAttrs;
- for (auto [llvmKind, mlirName] : kindNamePairs) {
+ for (auto [llvmKind, mlirName] : getAttrKindToNameMapping()) {
auto llvmAttr = llvmParamAttrs.getAttribute(llvmKind);
// Skip attributes that are not attached.
if (!llvmAttr.isValid())
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index b5323de221d7d..5f4833279eb5f 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -13,6 +13,7 @@
#include "mlir/Target/LLVMIR/ModuleTranslation.h"
+#include "AttrKindDetail.h"
#include "DebugTranslation.h"
#include "mlir/Dialect/DLTI/DLTI.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
@@ -29,6 +30,7 @@
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/TypeSwitch.h"
#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
@@ -899,42 +901,27 @@ static void convertFunctionAttributes(LLVMFuncOp func,
llvm::AttrBuilder
ModuleTranslation::convertParameterAttrs(DictionaryAttr paramAttrs) {
llvm::AttrBuilder attrBuilder(llvmModule->getContext());
- if (auto attr = paramAttrs.getAs<UnitAttr>(LLVMDialect::getNoAliasAttrName()))
- attrBuilder.addAttribute(llvm::Attribute::AttrKind::NoAlias);
-
- if (auto attr =
- paramAttrs.getAs<UnitAttr>(LLVMDialect::getReadonlyAttrName()))
- attrBuilder.addAttribute(llvm::Attribute::AttrKind::ReadOnly);
-
- if (auto attr =
- paramAttrs.getAs<IntegerAttr>(LLVMDialect::getAlignAttrName()))
- attrBuilder.addAlignmentAttr(llvm::Align(attr.getInt()));
-
- if (auto attr =
- paramAttrs.getAs<TypeAttr>(LLVMDialect::getStructRetAttrName()))
- attrBuilder.addStructRetAttr(convertType(attr.getValue()));
-
- if (auto attr = paramAttrs.getAs<TypeAttr>(LLVMDialect::getByValAttrName()))
- attrBuilder.addByValAttr(convertType(attr.getValue()));
- if (auto attr = paramAttrs.getAs<TypeAttr>(LLVMDialect::getByRefAttrName()))
- attrBuilder.addByRefAttr(convertType(attr.getValue()));
-
- if (auto attr =
- paramAttrs.getAs<TypeAttr>(LLVMDialect::getInAllocaAttrName()))
- attrBuilder.addInAllocaAttr(convertType(attr.getValue()));
-
- if (auto attr = paramAttrs.getAs<UnitAttr>(LLVMDialect::getNestAttrName()))
- attrBuilder.addAttribute(llvm::Attribute::Nest);
-
- if (auto attr = paramAttrs.getAs<UnitAttr>(LLVMDialect::getNoUndefAttrName()))
- attrBuilder.addAttribute(llvm::Attribute::NoUndef);
+ for (auto [llvmKind, mlirName] : getAttrKindToNameMapping()) {
+ Attribute attr = paramAttrs.get(mlirName);
+ // Skip attributes that are not present.
+ if (!attr)
+ continue;
- if (auto attr = paramAttrs.getAs<UnitAttr>(LLVMDialect::getSExtAttrName()))
- attrBuilder.addAttribute(llvm::Attribute::SExt);
+ // NOTE: C++17 does not support capturing structured bindings.
+ llvm::Attribute::AttrKind llvmKindCap = llvmKind;
+
+ llvm::TypeSwitch<Attribute>(attr)
+ .Case<TypeAttr>([&](auto typeAttr) {
+ attrBuilder.addTypeAttr(llvmKindCap,
+ convertType(typeAttr.getValue()));
+ })
+ .Case<IntegerAttr>([&](auto intAttr) {
+ attrBuilder.addRawIntAttr(llvmKindCap, intAttr.getInt());
+ })
+ .Case<UnitAttr>([&](auto) { attrBuilder.addAttribute(llvmKindCap); });
+ }
- if (auto attr = paramAttrs.getAs<UnitAttr>(LLVMDialect::getZExtAttrName()))
- attrBuilder.addAttribute(llvm::Attribute::ZExt);
return attrBuilder;
}
diff --git a/mlir/test/Dialect/LLVMIR/parameter-attrs-invalid.mlir b/mlir/test/Dialect/LLVMIR/parameter-attrs-invalid.mlir
index f6305f171013c..72bf45052ef13 100644
--- a/mlir/test/Dialect/LLVMIR/parameter-attrs-invalid.mlir
+++ b/mlir/test/Dialect/LLVMIR/parameter-attrs-invalid.mlir
@@ -107,6 +107,97 @@ llvm.func @invalid_noundef_attr_type(%0 : i32 {llvm.noundef = !llvm.ptr})
// -----
+// expected-error at below {{"llvm.dereferenceable" attribute attached to non-pointer LLVM type}}
+llvm.func @invalid_dereferenceable_arg_type(%0 : f32 {llvm.dereferenceable = 12 : i64})
+
+// -----
+
+// expected-error at below {{"llvm.dereferenceable" should be an integer attribute}}
+llvm.func @invalid_dereferenceable_attr_type(%0 : !llvm.ptr {llvm.dereferenceable = !llvm.struct<(i32)>})
+
+// -----
+
+// expected-error at below {{"llvm.dereferenceable_or_null" attribute attached to non-pointer LLVM type}}
+llvm.func @invalid_dereferenceable_or_null_arg_type(%0 : f32 {llvm.dereferenceable_or_null = 12 : i64})
+
+// -----
+
+// expected-error at below {{"llvm.dereferenceable_or_null" should be an integer attribute}}
+llvm.func @invalid_dereferenceable_or_null_attr_type(%0 : !llvm.ptr {llvm.dereferenceable_or_null = !llvm.struct<(i32)>})
+
+// -----
+
+// expected-error at below {{"llvm.inreg" should be a unit attribute}}
+llvm.func @invalid_inreg_attr_type(%0 : i32 {llvm.inreg = !llvm.ptr})
+
+// -----
+
+// expected-error at below {{"llvm.nocapture" attribute attached to non-pointer LLVM type}}
+llvm.func @invalid_nocapture_arg_type(%0 : f32 {llvm.nocapture})
+
+// -----
+
+// expected-error at below {{"llvm.nocapture" should be a unit attribute}}
+llvm.func @invalid_nocapture_attr_type(%0 : !llvm.ptr {llvm.nocapture = f32})
+
+// -----
+
+// expected-error at below {{"llvm.nofree" attribute attached to non-pointer LLVM type}}
+llvm.func @invalid_nofree_arg_type(%0 : f32 {llvm.nofree})
+
+// -----
+
+// expected-error at below {{"llvm.nofree" should be a unit attribute}}
+llvm.func @invalid_nofree_attr_type(%0 : !llvm.ptr {llvm.nofree = f32})
+
+// -----
+
+// expected-error at below {{"llvm.nonnull" attribute attached to non-pointer LLVM type}}
+llvm.func @invalid_nonnull_arg_type(%0 : f32 {llvm.nonnull})
+
+// -----
+
+// expected-error at below {{"llvm.nonnull" should be a unit attribute}}
+llvm.func @invalid_nonnull_attr_type(%0 : !llvm.ptr {llvm.nonnull = f32})
+
+// -----
+
+// expected-error at below {{"llvm.preallocated" attribute attached to non-pointer LLVM type}}
+llvm.func @invalid_preallocated_arg_type(%0 : f32 {llvm.preallocated = i64})
+
+// -----
+
+// expected-error at below {{"llvm.preallocated" should be a type attribute}}
+llvm.func @invalid_preallocated_attr_type(%0 : !llvm.ptr {llvm.preallocated})
+
+// -----
+
+// expected-error at below {{"llvm.returned" should be a unit attribute}}
+llvm.func @invalid_returned_attr_type(%0 : i32 {llvm.returned = !llvm.ptr})
+
+// -----
+
+// expected-error at below {{"llvm.alignstack" attribute attached to non-pointer LLVM type}}
+llvm.func @invalid_alignstack_arg_type(%0 : i32 {llvm.alignstack = 10 : i32})
+
+// -----
+
+// expected-error at below {{"llvm.alignstack" should be an integer attribute}}
+llvm.func @invalid_alignstack_attr_type(%0 : i32 {llvm.alignstack = "foo"})
+
+// -----
+
+// expected-error at below {{"llvm.writeonly" attribute attached to non-pointer LLVM type}}
+llvm.func @invalid_writeonly_arg_type(%0 : i32 {llvm.writeonly})
+
+// -----
+
+// expected-error at below {{"llvm.writeonly" should be a unit attribute}}
+llvm.func @invalid_writeonly_attr_type(%0 : i32 {llvm.writeonly = i32})
+
+// -----
+
+
// Result attributes
// expected-error at below {{cannot attach result attributes to functions with a void return}}
@@ -159,18 +250,13 @@ llvm.func @zeroextattr_ret() -> (f32 {llvm.zeroext})
// -----
-// expected-error @below{{"llvm.readonly" is not a valid result attribute}}
-llvm.func @readonly_ret() -> (f32 {llvm.readonly})
+// expected-error @below{{"llvm.allocalign" is not a valid result attribute}}
+llvm.func @allocalign_ret() -> (f32 {llvm.allocalign})
// -----
-// expected-error @below{{"llvm.nest" is not a valid result attribute}}
-llvm.func @nest_ret() -> (f32 {llvm.nest})
-
-// -----
-
-// expected-error @below{{"llvm.sret" is not a valid result attribute}}
-llvm.func @sret_ret() -> (!llvm.ptr {llvm.sret = i64})
+// expected-error @below{{"llvm.allocptr" is not a valid result attribute}}
+llvm.func @allocptr_ret() -> (!llvm.ptr {llvm.allocptr})
// -----
@@ -186,3 +272,48 @@ llvm.func @byref_ret() -> (!llvm.ptr {llvm.byref = i64})
// expected-error @below{{"llvm.inalloca" is not a valid result attribute}}
llvm.func @inalloca_ret() -> (!llvm.ptr {llvm.inalloca = i64})
+
+// -----
+
+// expected-error @below{{"llvm.nest" is not a valid result attribute}}
+llvm.func @nest_ret() -> (!llvm.ptr {llvm.nest})
+
+// -----
+
+// expected-error @below{{"llvm.nocapture" is not a valid result attribute}}
+llvm.func @nocapture_ret() -> (!llvm.ptr {llvm.nocapture})
+
+// -----
+
+// expected-error @below{{"llvm.nofree" is not a valid result attribute}}
+llvm.func @nofree_ret() -> (!llvm.ptr {llvm.nofree})
+
+// -----
+
+// expected-error @below{{"llvm.preallocated" is not a valid result attribute}}
+llvm.func @preallocated_ret() -> (!llvm.ptr {llvm.preallocated = i64})
+
+// -----
+
+// expected-error @below{{"llvm.readnone" is not a valid result attribute}}
+llvm.func @readnone_ret() -> (!llvm.ptr {llvm.readnone})
+
+// -----
+
+// expected-error @below{{"llvm.readonly" is not a valid result attribute}}
+llvm.func @readonly_ret() -> (!llvm.ptr {llvm.readonly})
+
+// -----
+
+// expected-error @below{{"llvm.alignstack" is not a valid result attribute}}
+llvm.func @alignstack_ret() -> (!llvm.ptr {llvm.alignstack = 16 : i64})
+
+// -----
+
+// expected-error @below{{"llvm.sret" is not a valid result attribute}}
+llvm.func @sret_ret() -> (!llvm.ptr {llvm.sret = i64})
+
+// -----
+
+// expected-error @below{{"llvm.writeonly" is not a valid result attribute}}
+llvm.func @writeonly_ret() -> (!llvm.ptr {llvm.writeonly})
diff --git a/mlir/test/Target/LLVMIR/Import/function-attributes.ll b/mlir/test/Target/LLVMIR/Import/function-attributes.ll
index ed38a160afa63..1d21b708bd309 100644
--- a/mlir/test/Target/LLVMIR/Import/function-attributes.ll
+++ b/mlir/test/Target/LLVMIR/Import/function-attributes.ll
@@ -37,7 +37,17 @@ attributes #0 = { readnone }
; CHECK-SAME: i32 {llvm.signext}
; CHECK-SAME: i64 {llvm.zeroext}
; CHECK-SAME: !llvm.ptr {llvm.align = 64 : i64, llvm.noundef}
-define void @func_arg_attrs(
+; CHECK-SAME: !llvm.ptr {llvm.dereferenceable = 12 : i64}
+; CHECK-SAME: !llvm.ptr {llvm.dereferenceable_or_null = 42 : i64}
+; CHECK-SAME: f64 {llvm.inreg}
+; CHECK-SAME: !llvm.ptr {llvm.nocapture}
+; CHECK-SAME: !llvm.ptr {llvm.nofree}
+; CHECK-SAME: !llvm.ptr {llvm.nonnull}
+; CHECK-SAME: !llvm.ptr {llvm.preallocated = f64}
+; CHECK-SAME: !llvm.ptr {llvm.returned}
+; CHECK-SAME: !llvm.ptr {llvm.alignstack = 32 : i64}
+; CHECK-SAME: !llvm.ptr {llvm.writeonly}
+define ptr @func_arg_attrs(
ptr byval(i64) %arg0,
ptr byref(i64) %arg1,
ptr sret(i64) %arg2,
@@ -47,15 +57,24 @@ define void @func_arg_attrs(
ptr nest %arg6,
i32 signext %arg7,
i64 zeroext %arg8,
- ptr align(64) noundef %arg9) {
- ret void
+ ptr align(64) noundef %arg9,
+ ptr dereferenceable(12) %arg10,
+ ptr dereferenceable_or_null(42) %arg11,
+ double inreg %arg12,
+ ptr nocapture %arg13,
+ ptr nofree %arg14,
+ ptr nonnull %arg15,
+ ptr preallocated(double) %arg16,
+ ptr returned %arg17,
+ ptr alignstack(32) %arg18,
+ ptr writeonly %arg19) {
+ ret ptr %arg17
}
-; // -----
-
-; CHECK-LABEL: @func_res_attr_align
-; CHECK-SAME: !llvm.ptr {llvm.align = 16 : i64}
-declare align(16) ptr @func_res_attr_align()
+; CHECK-LABEL: @allocator
+; CHECK-SAME: i64 {llvm.allocalign}
+; CHECK-SAME: ptr {llvm.allocptr}
+declare ptr @allocator(i64 allocalign, ptr allocptr)
; // -----
@@ -65,6 +84,12 @@ declare noalias ptr @func_res_attr_noalias()
; // -----
+; CHECK-LABEL: @func_res_attr_nonnull
+; CHECK-SAME: !llvm.ptr {llvm.nonnull}
+declare nonnull ptr @func_res_attr_nonnull()
+
+; // -----
+
; CHECK-LABEL: @func_res_attr_signext
; CHECK-DAG: llvm.noundef
; CHECK-DAG: llvm.signext
@@ -76,6 +101,35 @@ declare noundef signext i32 @func_res_attr_signext()
; CHECK-SAME: i32 {llvm.zeroext}
declare zeroext i32 @func_res_attr_zeroext()
+; // -----
+
+; CHECK-LABEL: @func_res_attr_align
+; CHECK-SAME: !llvm.ptr {llvm.align = 16 : i64}
+declare align(16) ptr @func_res_attr_align()
+
+; // -----
+
+; CHECK-LABEL: @func_res_attr_noundef
+; CHECK-SAME: !llvm.ptr {llvm.noundef}
+declare noundef ptr @func_res_attr_noundef()
+
+; // -----
+
+; CHECK-LABEL: @func_res_attr_dereferenceable
+; CHECK-SAME: !llvm.ptr {llvm.dereferenceable = 42 : i64}
+declare dereferenceable(42) ptr @func_res_attr_dereferenceable()
+
+; // -----
+
+; CHECK-LABEL: @func_res_attr_dereferenceable_or_null
+; CHECK-SAME: !llvm.ptr {llvm.dereferenceable_or_null = 42 : i64}
+declare dereferenceable_or_null(42) ptr @func_res_attr_dereferenceable_or_null()
+
+; // -----
+
+; CHECK-LABEL: @func_res_attr_inreg
+; CHECK-SAME: !llvm.ptr {llvm.inreg}
+declare inreg ptr @func_res_attr_inreg()
; // -----
diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir
index dde4bb3d95e76..4c4e85ce08add 100644
--- a/mlir/test/Target/LLVMIR/llvmir.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir.mlir
@@ -1124,17 +1124,66 @@ 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 void @alignattr_decl(ptr align 64)
+llvm.func @alignattr_decl(!llvm.ptr {llvm.align = 64 : i64})
+
+// CHECK-LABEL: declare void @dereferenceableattr_decl(ptr dereferenceable(32))
+llvm.func @dereferenceableattr_decl(!llvm.ptr {llvm.dereferenceable = 32 : i64})
+
+// CHECK-LABEL: declare void @dereferenceableornullattr_decl(ptr dereferenceable_or_null(32))
+llvm.func @dereferenceableornullattr_decl(!llvm.ptr {llvm.dereferenceable_or_null = 32 : i64})
+
+// CHECK-LABEL: declare void @inregattr_decl(ptr inreg)
+llvm.func @inregattr_decl(!llvm.ptr {llvm.inreg})
+
+// CHECK-LABEL: declare void @nocaptureattr_decl(ptr nocapture)
+llvm.func @nocaptureattr_decl(!llvm.ptr {llvm.nocapture})
+
+// CHECK-LABEL: declare void @nofreeattr_decl(ptr nofree)
+llvm.func @nofreeattr_decl(!llvm.ptr {llvm.nofree})
+
+// CHECK-LABEL: declare void @nonnullattr_decl(ptr nonnull)
+llvm.func @nonnullattr_decl(!llvm.ptr {llvm.nonnull})
+
+// CHECK-LABEL: declare void @preallocatedattr_decl(ptr preallocated(float))
+llvm.func @preallocatedattr_decl(!llvm.ptr {llvm.preallocated = f32})
+
+// CHECK-LABEL: declare ptr @returnedattr_decl(ptr returned)
+llvm.func @returnedattr_decl(!llvm.ptr {llvm.returned}) -> !llvm.ptr
+
+// CHECK-LABEL: declare void @alignstackattr_decl(ptr alignstack(32))
+llvm.func @alignstackattr_decl(!llvm.ptr {llvm.alignstack = 32 : i64})
+
+// CHECK-LABEL: declare void @writeonlyattr_decl(ptr writeonly)
+llvm.func @writeonlyattr_decl(!llvm.ptr {llvm.writeonly})
+
// 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: declare nonnull ptr @nonnullattr_ret_decl()
+llvm.func @nonnullattr_ret_decl() -> (!llvm.ptr {llvm.nonnull})
+
+// CHECK-LABEL: declare dereferenceable(32) ptr @dereferenceableattr_ret_decl()
+llvm.func @dereferenceableattr_ret_decl() -> (!llvm.ptr {llvm.dereferenceable = 32 : i64})
+
+// CHECK-LABEL: declare dereferenceable_or_null(16) ptr @dereferenceableornullattr_ret_decl()
+llvm.func @dereferenceableornullattr_ret_decl() -> (!llvm.ptr {llvm.dereferenceable_or_null = 16 : i64})
+
+// CHECK-LABEL: declare inreg ptr @inregattr_ret_decl()
+llvm.func @inregattr_ret_decl() -> (!llvm.ptr {llvm.inreg})
+
// CHECK-LABEL: @llvm_varargs(...)
llvm.func @llvm_varargs(...)
More information about the Mlir-commits
mailing list