[Mlir-commits] [mlir] 5494194 - [mlir][LLVM] Add all LLVM parameter attributes
Christian Ulmann
llvmlistbot at llvm.org
Sun Jan 29 23:57:06 PST 2023
Author: Christian Ulmann
Date: 2023-01-30T08:51:03+01:00
New Revision: 54941942c82f3a1640d50c0e354d29a3cf5535f6
URL: https://github.com/llvm/llvm-project/commit/54941942c82f3a1640d50c0e354d29a3cf5535f6
DIFF: https://github.com/llvm/llvm-project/commit/54941942c82f3a1640d50c0e354d29a3cf5535f6.diff
LOG: [mlir][LLVM] Add all LLVM parameter attributes
This commit adds name accessors and verifiers for all LLVM parameter
attributes excluding the swift specific ones to the LLVM dialect.
Additionally, these attributes are now also imported and exported.
Reviewed By: gysit
Differential Revision: https://reviews.llvm.org/D142635
Added:
mlir/lib/Target/LLVMIR/AttrKindDetail.cpp
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/CMakeLists.txt
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 017a59b0b2066..de6551f9f8f76 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -3226,7 +3226,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()))
@@ -3238,7 +3243,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()))
@@ -3257,7 +3263,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()))
@@ -3265,8 +3274,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();
}
@@ -3301,12 +3314,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.cpp b/mlir/lib/Target/LLVMIR/AttrKindDetail.cpp
new file mode 100644
index 0000000000000..2b41a73034d84
--- /dev/null
+++ b/mlir/lib/Target/LLVMIR/AttrKindDetail.cpp
@@ -0,0 +1,42 @@
+#include "AttrKindDetail.h"
+
+llvm::ArrayRef<std::pair<llvm::Attribute::AttrKind, llvm::StringRef>>
+mlir::LLVM::detail::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;
+}
diff --git a/mlir/lib/Target/LLVMIR/AttrKindDetail.h b/mlir/lib/Target/LLVMIR/AttrKindDetail.h
new file mode 100644
index 0000000000000..b4259f3c05f73
--- /dev/null
+++ b/mlir/lib/Target/LLVMIR/AttrKindDetail.h
@@ -0,0 +1,28 @@
+//===- 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.
+llvm::ArrayRef<std::pair<llvm::Attribute::AttrKind, llvm::StringRef>>
+getAttrKindToNameMapping();
+
+} // namespace detail
+} // namespace LLVM
+} // namespace mlir
+
+#endif // ATTRKINDDETAIL_H_
diff --git a/mlir/lib/Target/LLVMIR/CMakeLists.txt b/mlir/lib/Target/LLVMIR/CMakeLists.txt
index 97577c036a220..257a2585bf941 100644
--- a/mlir/lib/Target/LLVMIR/CMakeLists.txt
+++ b/mlir/lib/Target/LLVMIR/CMakeLists.txt
@@ -1,6 +1,7 @@
add_subdirectory(Dialect)
set(LLVM_OPTIONAL_SOURCES
+ AttrKindDetail.cpp
ConvertFromLLVMIR.cpp
ConvertToLLVMIR.cpp
DebugTranslation.cpp
@@ -13,6 +14,7 @@ set(LLVM_OPTIONAL_SOURCES
add_mlir_translation_library(MLIRTargetLLVMIRExport
+ AttrKindDetail.cpp
DebugTranslation.cpp
ModuleTranslation.cpp
TypeToLLVM.cpp
@@ -52,6 +54,7 @@ add_mlir_translation_library(MLIRToLLVMIRTranslationRegistration
)
add_mlir_translation_library(MLIRTargetLLVMIRImport
+ AttrKindDetail.cpp
DebugImporter.cpp
ModuleImport.cpp
TypeFromLLVM.cpp
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 5391d2e92f45e..f86e2e7a53a19 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"
@@ -1490,24 +1491,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