blob: 66a1fe0ce251af1793cefe377face2b2691695b5 [file]
//===-- LLVMInterfaces.td - LLVM Interfaces ----------------*- tablegen -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file defines interfaces for the LLVM dialect in MLIR.
//
//===----------------------------------------------------------------------===//
#ifndef LLVMIR_INTERFACES
#define LLVMIR_INTERFACES
include "mlir/IR/OpBase.td"
include "mlir/Interfaces/DataLayoutInterfaces.td"
def FastmathFlagsInterface : OpInterface<"FastmathFlagsInterface"> {
let description = [{
Access to op fastmath flags.
}];
let cppNamespace = "::mlir::LLVM";
let methods = [
InterfaceMethod<
/*desc=*/ "Returns a FastmathFlagsAttr attribute for the operation",
/*returnType=*/ "::mlir::LLVM::FastmathFlagsAttr",
/*methodName=*/ "getFastmathAttr",
/*args=*/ (ins),
/*methodBody=*/ [{}],
/*defaultImpl=*/ [{
auto op = cast<ConcreteOp>(this->getOperation());
return op.getFastmathFlagsAttr();
}]
>,
InterfaceMethod<
/*desc=*/ "Sets the FastmathFlagsAttr attribute for the operation",
/*returnType=*/ "void",
/*methodName=*/ "setFastmathAttr",
/*args=*/ (ins "::mlir::LLVM::FastmathFlagsAttr":$attr),
/*methodBody=*/ [{}],
/*defaultImpl=*/ [{
auto op = cast<ConcreteOp>(this->getOperation());
op.setFastmathFlagsAttr(attr);
}]
>,
StaticInterfaceMethod<
/*desc=*/ [{Returns the name of the FastmathFlagsAttr attribute
for the operation}],
/*returnType=*/ "::llvm::StringRef",
/*methodName=*/ "getFastmathAttrName",
/*args=*/ (ins),
/*methodBody=*/ [{}],
/*defaultImpl=*/ [{
return "fastmathFlags";
}]
>
];
}
def IntegerOverflowFlagsInterface : OpInterface<"IntegerOverflowFlagsInterface"> {
let description = [{
This interface defines an LLVM operation with integer overflow flags and
provides a uniform API for accessing them.
}];
let cppNamespace = "::mlir::LLVM";
let methods = [
InterfaceMethod<[{
Get the integer overflow flags for the operation.
}], "IntegerOverflowFlags", "getOverflowFlags", (ins), [{}], [{
return $_op.getProperties().overflowFlags;
}]>,
InterfaceMethod<[{
Set the integer overflow flags for the operation.
}], "void", "setOverflowFlags", (ins "IntegerOverflowFlags":$flags), [{}], [{
$_op.getProperties().overflowFlags = flags;
}]>,
InterfaceMethod<[{
Returns whether the operation has the No Unsigned Wrap keyword.
}], "bool", "hasNoUnsignedWrap", (ins), [{}], [{
return bitEnumContainsAll($_op.getOverflowFlags(),
IntegerOverflowFlags::nuw);
}]>,
InterfaceMethod<[{
Returns whether the operation has the No Signed Wrap keyword.
}], "bool", "hasNoSignedWrap", (ins), [{}], [{
return bitEnumContainsAll($_op.getOverflowFlags(),
IntegerOverflowFlags::nsw);
}]>,
StaticInterfaceMethod<[{
Get the attribute name of the overflow flags property.
}], "StringRef", "getOverflowFlagsAttrName", (ins), [{}], [{
return "overflowFlags";
}]>,
];
}
def ExactFlagInterface : OpInterface<"ExactFlagInterface"> {
let description = [{
This interface defines an LLVM operation with an exact flag and
provides a uniform API for accessing it.
}];
let cppNamespace = "::mlir::LLVM";
let methods = [
InterfaceMethod<[{
Get the exact flag for the operation.
}], "bool", "getIsExact", (ins), [{}], [{
return $_op.getProperties().isExact;
}]>,
InterfaceMethod<[{
Set the exact flag for the operation.
}], "void", "setIsExact", (ins "bool":$isExact), [{}], [{
$_op.getProperties().isExact = isExact;
}]>,
StaticInterfaceMethod<[{
Get the attribute name of the isExact property.
}], "StringRef", "getIsExactName", (ins), [{}], [{
return "isExact";
}]>,
];
}
def DisjointFlagInterface : OpInterface<"DisjointFlagInterface"> {
let description = [{
This interface defines an LLVM operation with a disjoint flag and
provides a uniform API for accessing it.
}];
let cppNamespace = "::mlir::LLVM";
let methods = [
InterfaceMethod<[{
Get the disjoint flag for the operation.
}], "bool", "getIsDisjoint", (ins), [{}], [{
return $_op.getProperties().isDisjoint;
}]>,
InterfaceMethod<[{
Set the disjoint flag for the operation.
}], "void", "setIsDisjoint", (ins "bool":$isDisjoint), [{}], [{
$_op.getProperties().isDisjoint = isDisjoint;
}]>,
StaticInterfaceMethod<[{
Get the attribute name of the isDisjoint property.
}], "StringRef", "getIsDisjointName", (ins), [{}], [{
return "isDisjoint";
}]>,
];
}
def NonNegFlagInterface : OpInterface<"NonNegFlagInterface"> {
let description = [{
This interface defines an LLVM operation with an nneg flag and
provides a uniform API for accessing it.
}];
let cppNamespace = "::mlir::LLVM";
let methods = [
InterfaceMethod<[{
Get the nneg flag for the operation.
}], "bool", "getNonNeg", (ins), [{}], [{
return $_op.getProperties().nonNeg;
}]>,
InterfaceMethod<[{
Set the nneg flag for the operation.
}], "void", "setNonNeg", (ins "bool":$nonNeg), [{}], [{
$_op.getProperties().nonNeg = nonNeg;
}]>,
StaticInterfaceMethod<[{
Get the attribute name of the nonNeg property.
}], "StringRef", "getNonNegName", (ins), [{}], [{
return "nonNeg";
}]>,
];
}
def AccessGroupOpInterface : OpInterface<"AccessGroupOpInterface"> {
let description = [{
An interface for memory operations that can carry access groups metadata.
It provides setters and getters for the operation's access groups attribute.
The default implementations of the interface methods expect the operation
to have an attribute of type ArrayAttr named access_groups.
}];
let cppNamespace = "::mlir::LLVM";
let verify = [{ return detail::verifyAccessGroupOpInterface($_op); }];
let methods = [
InterfaceMethod<
/*desc=*/ "Returns the access groups attribute or nullptr",
/*returnType=*/ "::mlir::ArrayAttr",
/*methodName=*/ "getAccessGroupsOrNull",
/*args=*/ (ins),
/*methodBody=*/ [{}],
/*defaultImpl=*/ [{
auto op = cast<ConcreteOp>(this->getOperation());
return op.getAccessGroupsAttr();
}]
>,
InterfaceMethod<
/*desc=*/ "Sets the access groups attribute",
/*returnType=*/ "void",
/*methodName=*/ "setAccessGroups",
/*args=*/ (ins "const ::mlir::ArrayAttr":$attr),
/*methodBody=*/ [{}],
/*defaultImpl=*/ [{
auto op = cast<ConcreteOp>(this->getOperation());
op.setAccessGroupsAttr(attr);
}]
>
];
}
def AliasAnalysisOpInterface : OpInterface<"AliasAnalysisOpInterface"> {
let description = [{
An interface for memory operations that can carry alias analysis metadata.
It provides setters and getters for the operation's alias analysis
attributes. The default implementations of the interface methods expect
the operation to have attributes of type ArrayAttr named alias_scopes,
noalias_scopes, and tbaa.
}];
let cppNamespace = "::mlir::LLVM";
let verify = [{ return detail::verifyAliasAnalysisOpInterface($_op); }];
let methods = [
InterfaceMethod<
/*desc=*/ "Returns the alias scopes attribute or nullptr",
/*returnType=*/ "::mlir::ArrayAttr",
/*methodName=*/ "getAliasScopesOrNull",
/*args=*/ (ins),
/*methodBody=*/ [{}],
/*defaultImpl=*/ [{
auto op = cast<ConcreteOp>(this->getOperation());
return op.getAliasScopesAttr();
}]
>,
InterfaceMethod<
/*desc=*/ "Sets the alias scopes attribute",
/*returnType=*/ "void",
/*methodName=*/ "setAliasScopes",
/*args=*/ (ins "const ::mlir::ArrayAttr":$attr),
/*methodBody=*/ [{}],
/*defaultImpl=*/ [{
auto op = cast<ConcreteOp>(this->getOperation());
op.setAliasScopesAttr(attr);
}]
>,
InterfaceMethod<
/*desc=*/ "Returns the noalias scopes attribute or nullptr",
/*returnType=*/ "::mlir::ArrayAttr",
/*methodName=*/ "getNoAliasScopesOrNull",
/*args=*/ (ins),
/*methodBody=*/ [{}],
/*defaultImpl=*/ [{
auto op = cast<ConcreteOp>(this->getOperation());
return op.getNoaliasScopesAttr();
}]
>,
InterfaceMethod<
/*desc=*/ "Sets the noalias scopes attribute",
/*returnType=*/ "void",
/*methodName=*/ "setNoAliasScopes",
/*args=*/ (ins "const ::mlir::ArrayAttr":$attr),
/*methodBody=*/ [{}],
/*defaultImpl=*/ [{
auto op = cast<ConcreteOp>(this->getOperation());
op.setNoaliasScopesAttr(attr);
}]
>,
InterfaceMethod<
/*desc=*/ "Returns the tbaa attribute or nullptr",
/*returnType=*/ "::mlir::ArrayAttr",
/*methodName=*/ "getTBAATagsOrNull",
/*args=*/ (ins),
/*methodBody=*/ [{}],
/*defaultImpl=*/ [{
auto op = cast<ConcreteOp>(this->getOperation());
return op.getTbaaAttr();
}]
>,
InterfaceMethod<
/*desc=*/ "Sets the tbaa attribute",
/*returnType=*/ "void",
/*methodName=*/ "setTBAATags",
/*args=*/ (ins "const ::mlir::ArrayAttr":$attr),
/*methodBody=*/ [{}],
/*defaultImpl=*/ [{
auto op = cast<ConcreteOp>(this->getOperation());
op.setTbaaAttr(attr);
}]
>,
InterfaceMethod<
/*desc=*/ "Returns a list of all pointer operands accessed by the "
"operation",
/*returnType=*/ "::llvm::SmallVector<::mlir::Value>",
/*methodName=*/ "getAccessedOperands",
/*args=*/ (ins)
>
];
}
def DereferenceableOpInterface : OpInterface<"DereferenceableOpInterface"> {
let description = [{
An interface for memory operations that can carry dereferenceable metadata.
It provides setters and getters for the operation's dereferenceable
attributes. The default implementations of the interface methods expect
the operation to have an attribute of type DereferenceableAttr.
}];
let cppNamespace = "::mlir::LLVM";
let verify = [{ return detail::verifyDereferenceableOpInterface($_op); }];
let methods = [
InterfaceMethod<
/*desc=*/ "Returns the dereferenceable attribute or nullptr",
/*returnType=*/ "::mlir::LLVM::DereferenceableAttr",
/*methodName=*/ "getDereferenceableOrNull",
/*args=*/ (ins),
/*methodBody=*/ [{}],
/*defaultImpl=*/ [{
auto op = cast<ConcreteOp>(this->getOperation());
return op.getDereferenceableAttr();
}]
>,
InterfaceMethod<
/*desc=*/ "Sets the dereferenceable attribute",
/*returnType=*/ "void",
/*methodName=*/ "setDereferenceable",
/*args=*/ (ins "::mlir::LLVM::DereferenceableAttr":$attr),
/*methodBody=*/ [{}],
/*defaultImpl=*/ [{
auto op = cast<ConcreteOp>(this->getOperation());
op.setDereferenceableAttr(attr);
}]
>
];
}
def FPExceptionBehaviorOpInterface : OpInterface<"FPExceptionBehaviorOpInterface"> {
let description = [{
An interface for operations receiving an exception behavior attribute
controlling FP exception behavior.
}];
let cppNamespace = "::mlir::LLVM";
let methods = [
InterfaceMethod<
/*desc=*/ "Returns a FPExceptionBehavior attribute for the operation",
/*returnType=*/ "::mlir::LLVM::FPExceptionBehaviorAttr",
/*methodName=*/ "getFPExceptionBehaviorAttr",
/*args=*/ (ins),
/*methodBody=*/ [{}],
/*defaultImpl=*/ [{
auto op = cast<ConcreteOp>(this->getOperation());
return op.getFpExceptionBehaviorAttr();
}]
>,
StaticInterfaceMethod<
/*desc=*/ [{Returns the name of the FPExceptionBehaviorAttr
attribute for the operation}],
/*returnType=*/ "::llvm::StringRef",
/*methodName=*/ "getFPExceptionBehaviorAttrName",
/*args=*/ (ins),
/*methodBody=*/ [{}],
/*defaultImpl=*/ [{
return "fpExceptionBehavior";
}]
>
];
}
def RoundingModeOpInterface : OpInterface<"RoundingModeOpInterface"> {
let description = [{
An interface for operations receiving a rounding mode attribute
controlling FP rounding mode.
}];
let cppNamespace = "::mlir::LLVM";
let methods = [
InterfaceMethod<
/*desc=*/ "Returns a RoundingMode attribute for the operation",
/*returnType=*/ "::mlir::LLVM::RoundingModeAttr",
/*methodName=*/ "getRoundingModeAttr",
/*args=*/ (ins),
/*methodBody=*/ [{}],
/*defaultImpl=*/ [{
auto op = cast<ConcreteOp>(this->getOperation());
return op.getRoundingmodeAttr();
}]
>,
StaticInterfaceMethod<
/*desc=*/ [{Returns the name of the RoundingModeAttr attribute
for the operation}],
/*returnType=*/ "::llvm::StringRef",
/*methodName=*/ "getRoundingModeAttrName",
/*args=*/ (ins),
/*methodBody=*/ [{}],
/*defaultImpl=*/ [{
return "roundingmode";
}]
>,
];
}
def OneToOneIntrinsicOpInterface : OpInterface<"OneToOneIntrinsicOpInterface"> {
let description = [{
An interface for operations modelling LLVM intrinsics suitable for
1-to-1 conversion.
An op implementing this interface can be directly replaced by a call
to a matching intrinsic function.
The op must ensure that the combinations of its arguments and results
have valid intrinsic counterparts.
For example, an operation supporting different inputs:
```mlir
%res_v8 = intr.op %value_v8 : vector<8xf32>
%res_v16 = intr.op %value_v16 : vector<16xf32>
```
can be converted to the following intrinsic calls:
```mlir
%res_v8 = llvm.call_intrinsic "llvm.x86.op.intr.256"(%value_v8)
%res_v16 = llvm.call_intrinsic "llvm.x86.op.intr.512"(%value_v16)
```
}];
let cppNamespace = "::mlir::LLVM";
let methods = [
InterfaceMethod<
/*desc=*/[{
Returns mangled LLVM intrinsic function name matching the operation
variant.
}],
/*retType=*/"std::string",
/*methodName=*/"getIntrinsicName"
>,
InterfaceMethod<
/*desc=*/[{
Returns operands for a corresponding LLVM intrinsic.
Additional operations may be created to facilitate mapping
between the source operands and the target intrinsic.
}],
/*retType=*/"SmallVector<Value>",
/*methodName=*/"getIntrinsicOperands",
/*args=*/(ins "::mlir::ArrayRef<Value>":$operands,
"const ::mlir::LLVMTypeConverter &":$typeConverter,
"::mlir::RewriterBase &":$rewriter),
/*methodBody=*/"",
/*defaultImplementation=*/"return SmallVector<Value>(operands);"
>,
];
}
//===----------------------------------------------------------------------===//
// LLVM dialect type interfaces.
//===----------------------------------------------------------------------===//
// An interface for LLVM pointer element types.
def LLVM_PointerElementTypeInterface
: TypeInterface<"PointerElementTypeInterface"> {
let cppNamespace = "::mlir::LLVM";
let description = [{
An interface for types that are allowed as elements of LLVM pointer type.
Such types must have a size.
}];
let methods = [
InterfaceMethod<
/*description=*/"Returns the size of the type in bytes.",
/*retTy=*/"unsigned",
/*methodName=*/"getSizeInBytes",
/*args=*/(ins "const ::mlir::DataLayout &":$dataLayout),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return dataLayout.getTypeSize($_type);
}]
>
];
}
//===----------------------------------------------------------------------===//
// LLVM dialect attr interfaces.
//===----------------------------------------------------------------------===//
def LLVM_DIRecursiveTypeAttrInterface
: AttrInterface<"DIRecursiveTypeAttrInterface"> {
let description = [{
This attribute represents a DITypeAttr that is recursive. Only DITypeAttrs
that translate to LLVM DITypes that support mutation should implement this
interface.
There are two modes for conforming attributes:
1. "rec-decl":
- This attr is a recursive declaration identified by a recId.
2. "rec-self":
- This attr is considered a recursive self reference.
- This attr itself is a placeholder type that should be conceptually
replaced with the closest parent attr of the same type with the same
recId.
For example, to represent a linked list struct:
#rec_self = di_composite_type<recId = 0>
#ptr = di_derived_type<baseType: #rec_self, ...>
#field = di_derived_type<name = "next", baseType: #ptr, ...>
#rec = di_composite_type<recId = 0, name = "Node", elements: #field, ...>
#var = di_local_variable<type = #rec, ...>
Note that a rec-self without an outer rec-decl with the same recId is
conceptually the same as an "unbound" variable. The context needs to provide
meaning to the rec-self.
}];
let cppNamespace = "::mlir::LLVM";
let methods = [
InterfaceMethod<[{
Get whether this attr describes a recursive self reference.
}], "bool", "getIsRecSelf", (ins)>,
InterfaceMethod<[{
Get the recursive ID used for matching "rec-decl" with "rec-self".
If this attr instance is not recursive, return a null attribute.
}], "DistinctAttr", "getRecId", (ins)>,
InterfaceMethod<[{
Get a copy of this type attr but with the recursive ID set to `recId`.
}], "DIRecursiveTypeAttrInterface", "withRecId",
(ins "DistinctAttr":$recId)>,
StaticInterfaceMethod<[{
Build a rec-self instance using the provided `recId`.
}], "DIRecursiveTypeAttrInterface", "getRecSelf",
(ins "DistinctAttr":$recId)>
];
}
def LLVM_LLVMAddrSpaceAttrInterface :
AttrInterface<"LLVMAddrSpaceAttrInterface"> {
let description = [{
An interface for attributes that represent LLVM address spaces.
Implementing attributes should provide access to the address space value
as an unsigned integer.
}];
let cppNamespace = "::mlir::LLVM";
let methods = [
InterfaceMethod<
/*description=*/"Returns the address space as an unsigned integer.",
/*retTy=*/"unsigned",
/*methodName=*/"getAddressSpace",
/*args=*/(ins)
>
];
}
def LLVM_IntrinsicIntegerAttrInterface :
AttrInterface<"IntrinsicIntegerAttrInterface"> {
let description = [{
An interface for attributes that represent LLVM intrinsic integer immediate
arguments while using a richer dialect-specific assembly form.
The default implementation is intended for enum-style attributes whose
`getValue()` returns an enum with a storage type that matches the LLVM
immarg width. Attributes with non-enum storage or a different LLVM immarg
width must override `getIntegerAttr`.
}];
let cppNamespace = "::mlir::LLVM";
let methods = [
InterfaceMethod<
/*description=*/"Returns the integer attribute to pass to LLVM.",
/*retTy=*/"::mlir::IntegerAttr",
/*methodName=*/"getIntegerAttr",
/*args=*/(ins),
/*methodBody=*/[{}],
/*defaultImplementation=*/[{
using EnumType = decltype($_attr.getValue());
using StorageType = std::underlying_type_t<EnumType>;
auto type = ::mlir::IntegerType::get($_attr.getContext(),
sizeof(StorageType) * 8);
return ::mlir::IntegerAttr::get(
type, static_cast<StorageType>($_attr.getValue()));
}]
>
];
}
def LLVM_ModuleFlagAttrInterface :
AttrInterface<"ModuleFlagAttrInterface"> {
let description = [{
An interface for attributes that represent LLVM module flag metadata entries.
Implementing attributes provide the module flag merge behavior, metadata key,
and metadata value. This lets target dialects define richer, target-specific
module flag attributes while still sharing `llvm.module_flags` as the common
operation container. Values returned by this interface must use a shape that
can be exported to LLVM IR: integer attributes (exported as i32 constants),
string attributes, attributes implementing `IntrinsicIntegerAttrInterface`,
supported array values, or `ModuleFlagProfileSummaryAttr`.
}];
let cppNamespace = "::mlir::LLVM";
let methods = [
InterfaceMethod<
/*description=*/"Returns the module flag merge behavior.",
/*retTy=*/"::mlir::LLVM::ModFlagBehavior",
/*methodName=*/"getModuleFlagBehavior",
/*args=*/(ins)
>,
InterfaceMethod<
/*description=*/"Returns the module flag metadata key.",
/*retTy=*/"::mlir::StringAttr",
/*methodName=*/"getModuleFlagKey",
/*args=*/(ins)
>,
InterfaceMethod<
/*description=*/"Returns the module flag metadata value.",
/*retTy=*/"::mlir::Attribute",
/*methodName=*/"getModuleFlagValue",
/*args=*/(ins)
>
];
}
def LLVM_TargetAttrInterface
: AttrInterface<"TargetAttrInterface", [DLTIQueryInterface]> {
let description = [{
Interface for attributes that describe LLVM targets.
These attributes should be able to return the specified target `triple`,
`chip` and `features`.
Implementing attributes should provide a `DLTIQueryInterface::query()`
implementation which responds to keys `"triple"`, `"chip"` and `"features"`
by returning appropriate `StringAttr`s.
}];
let cppNamespace = "::mlir::LLVM";
let methods = [
InterfaceMethod<
/*description=*/"Returns the target triple identifier.",
/*retTy=*/"StringAttr",
/*methodName=*/"getTriple",
/*args=*/(ins)
>,
InterfaceMethod<
/*description=*/"Returns the target chip (i.e. \"cpu\") identifier.",
/*retTy=*/"StringAttr",
/*methodName=*/"getChip",
/*args=*/(ins)
>,
InterfaceMethod<
/*description=*/"Returns the target features as a TargetFeaturesAttr.",
/*retTy=*/"Attribute", // NB: will be a LLVM::TargetFeaturesAttr, though
// need to work around a cyclic dependency on
// LLVMInterfaces.td and LLVMAttrDefs.td.
/*methodName=*/"getFeatures",
/*args=*/(ins)
>
];
}
#endif // LLVMIR_INTERFACES