Skip to content

Commit 35fe2c9

Browse files
committed
[MLIR][LLVMIR][DLTI] Add LLVMTargetAttrInterface, #llvm.target and #llvm.data_layout
1 parent ac42923 commit 35fe2c9

19 files changed

+462
-98
lines changed

mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,21 @@ mlir_tablegen(LLVMOpsDialect.h.inc -gen-dialect-decls)
77
mlir_tablegen(LLVMOpsDialect.cpp.inc -gen-dialect-defs)
88
mlir_tablegen(LLVMOpsEnums.h.inc -gen-enum-decls)
99
mlir_tablegen(LLVMOpsEnums.cpp.inc -gen-enum-defs)
10-
mlir_tablegen(LLVMOpsAttrDefs.h.inc -gen-attrdef-decls
11-
-attrdefs-dialect=llvm)
1210
mlir_tablegen(LLVMOpsAttrDefs.cpp.inc -gen-attrdef-defs
1311
-attrdefs-dialect=llvm)
1412
add_public_tablegen_target(MLIRLLVMOpsIncGen)
1513

14+
# FIXME: explain how this solves generated header recursive dependency
15+
set(LLVM_TARGET_DEFINITIONS LLVMAttrAndEnumDefs.td)
16+
mlir_tablegen(LLVMOpsAttrDefs.h.inc -gen-attrdef-decls -attrdefs-dialect=llvm)
17+
add_public_tablegen_target(MLIRLLVMAttrsIncGen)
18+
19+
# FIXME: explain how this solves generated header recursive dependency
20+
set(LLVM_TARGET_DEFINITIONS LLVMTargetFeaturesAttrDefs.td)
21+
mlir_tablegen(LLVMTargetFeaturesAttrDefs.h.inc -gen-attrdef-decls)
22+
mlir_tablegen(LLVMTargetFeaturesAttrDefs.cpp.inc -gen-attrdef-defs)
23+
add_public_tablegen_target(MLIRLLVMTargetFeaturesAttrsIncGen)
24+
1625
set(LLVM_TARGET_DEFINITIONS LLVMTypes.td)
1726
mlir_tablegen(LLVMTypes.h.inc -gen-typedef-decls -typedefs-dialect=llvm)
1827
mlir_tablegen(LLVMTypes.cpp.inc -gen-typedef-defs -typedefs-dialect=llvm)

mlir/lib/Target/LLVMIR/DataLayoutImporter.h renamed to mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@
1111
//
1212
//===----------------------------------------------------------------------===//
1313

14-
#ifndef MLIR_LIB_TARGET_LLVMIR_DATALAYOUTIMPORTER_H_
15-
#define MLIR_LIB_TARGET_LLVMIR_DATALAYOUTIMPORTER_H_
14+
#ifndef MLIR_LLVMIR_DATALAYOUTIMPORTER_H_
15+
#define MLIR_LLVMIR_DATALAYOUTIMPORTER_H_
1616

1717
#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
1818
#include "mlir/IR/BuiltinAttributes.h"
1919
#include "mlir/Interfaces/DataLayoutInterfaces.h"
20+
#include "llvm/IR/DataLayout.h"
2021
#include "llvm/ADT/MapVector.h"
2122

2223
namespace llvm {
@@ -38,6 +39,8 @@ namespace detail {
3839
/// null if the bit width is not supported.
3940
FloatType getFloatType(MLIRContext *context, unsigned width);
4041

42+
} // namespace detail
43+
4144
/// Helper class that translates an LLVM data layout to an MLIR data layout
4245
/// specification. Only integer, float, pointer, alloca memory space, stack
4346
/// alignment, and endianness entries are translated. The class also returns all
@@ -49,7 +52,22 @@ class DataLayoutImporter {
4952
DataLayoutImporter(MLIRContext *context,
5053
const llvm::DataLayout &llvmDataLayout)
5154
: context(context) {
52-
translateDataLayout(llvmDataLayout);
55+
// Transform the data layout to its string representation and append the
56+
// default data layout string specified in the language reference
57+
// (https://llvm.org/docs/LangRef.html#data-layout). The translation then
58+
// parses the string and ignores the default value if a specific kind occurs
59+
// in both strings. Additionally, the following default values exist:
60+
// - non-default address space pointer specifications default to the default
61+
// address space pointer specification
62+
// - the alloca address space defaults to the default address space.
63+
layoutStr = llvmDataLayout.getStringRepresentation();
64+
translateDataLayoutFromStr();
65+
}
66+
67+
DataLayoutImporter(MLIRContext *context,
68+
StringRef dataLayoutStr)
69+
: layoutStr(dataLayoutStr), context(context) {
70+
translateDataLayoutFromStr();
5371
}
5472

5573
/// Returns the MLIR data layout specification translated from the LLVM
@@ -66,7 +84,7 @@ class DataLayoutImporter {
6684

6785
private:
6886
/// Translates the LLVM `dataLayout` to an MLIR data layout specification.
69-
void translateDataLayout(const llvm::DataLayout &llvmDataLayout);
87+
void translateDataLayoutFromStr();
7088

7189
/// Tries to parse the letter only prefix that identifies the specification
7290
/// and removes the consumed characters from the beginning of the string.
@@ -125,8 +143,7 @@ class DataLayoutImporter {
125143
DataLayoutSpecInterface dataLayout;
126144
};
127145

128-
} // namespace detail
129146
} // namespace LLVM
130147
} // namespace mlir
131148

132-
#endif // MLIR_LIB_TARGET_LLVMIR_DATALAYOUTIMPORTER_H_
149+
#endif // MLIR_LLVMIR_DATALAYOUTIMPORTER_H_
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//===-- LLVMAttrDefs.td - Solely LLVM Attribute and Enum definitions ----*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
include "mlir/Dialect/LLVMIR/LLVMAttrDefs.td"
10+
include "mlir/Dialect/LLVMIR/LLVMEnums.td"

mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td

Lines changed: 111 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,118 @@ include "mlir/Dialect/LLVMIR/LLVMDialect.td"
1313
include "mlir/Dialect/LLVMIR/LLVMInterfaces.td"
1414
include "mlir/IR/AttrTypeBase.td"
1515
include "mlir/IR/CommonAttrConstraints.td"
16+
include "mlir/Interfaces/DataLayoutInterfaces.td"
1617

17-
// All of the attributes will extend this class.
18-
class LLVM_Attr<string name, string attrMnemonic,
19-
list<Trait> traits = [],
20-
string baseCppClass = "::mlir::Attribute">
21-
: AttrDef<LLVM_Dialect, name, traits, baseCppClass> {
22-
let mnemonic = attrMnemonic;
18+
//===----------------------------------------------------------------------===//
19+
// LLVM_TargetAttr
20+
//===----------------------------------------------------------------------===//
21+
22+
def LLVM_TargetAttr : LLVM_Attr<"Target", "target", [LLVM_TargetAttrInterface]> {
23+
let mnemonic = "target";
24+
let summary = "TODO";
25+
let description = [{
26+
TODO
27+
}];
28+
let parameters = (ins "StringAttr":$triple,
29+
"StringAttr":$cpu,
30+
"TargetFeaturesAttr":$target_features);
31+
32+
let assemblyFormat = "`<` $triple `,` $cpu `,` qualified($target_features) `>`";
33+
34+
let extraClassDeclaration = [{
35+
std::optional<llvm::TargetMachine *> targetMachine = std::nullopt;
36+
37+
FailureOr<llvm::TargetMachine *> getTargetMachine();
38+
39+
std::optional<llvm::DataLayout> dataLayout = std::nullopt;
40+
FailureOr<llvm::DataLayout> getDataLayout();
41+
FailureOr<Attribute> query(DataLayoutEntryKey key);
42+
}];
43+
}
44+
45+
//===----------------------------------------------------------------------===//
46+
// LLVM_DataLayoutAttr
47+
//===----------------------------------------------------------------------===//
48+
49+
def LLVM_DataLayoutAttr
50+
: LLVM_Attr<"DataLayout", "data_layout", [DataLayoutSpecInterface]> {
51+
let summary = "TODO";
52+
let description = [{
53+
TODO
54+
}];
55+
let parameters = (ins "StringAttr":$data_layout_str,
56+
OptionalParameter<"DataLayoutSpecInterface", "{}">:$data_layout_spec);
57+
let builders = [
58+
AttrBuilder<(ins "llvm::StringRef":$data_layout_str), [{
59+
auto importer = LLVM::DataLayoutImporter($_ctxt, data_layout_str);
60+
auto dataLayoutSpec = importer.getDataLayout();
61+
return $_get($_ctxt, mlir::StringAttr::get($_ctxt, data_layout_str), dataLayoutSpec);
62+
}]>
63+
];
64+
let assemblyFormat = "`<` $data_layout_str `>`";
65+
let extraClassDeclaration = [{
66+
template <typename Ty>
67+
DataLayoutEntryList getSpecForType() {
68+
return getDataLayoutSpec().getSpecForType(TypeID::get<Ty>());
69+
}
70+
71+
inline ::mlir::FailureOr<::mlir::Attribute>
72+
queryHelper(::mlir::DataLayoutEntryKey key) const {
73+
return getDataLayoutSpec().queryHelper(key);
74+
}
75+
76+
void bucketEntriesByType(
77+
::llvm::MapVector<::mlir::TypeID, ::mlir::DataLayoutEntryList> &types,
78+
::llvm::MapVector<::mlir::StringAttr,
79+
::mlir::DataLayoutEntryInterface> &ids) {
80+
getDataLayoutSpec().bucketEntriesByType(types, ids);
81+
};
82+
83+
::mlir::DataLayoutSpecInterface
84+
combineWith(ArrayRef<::mlir::DataLayoutSpecInterface> specs) const {
85+
return getDataLayoutSpec().combineWith(specs);
86+
}
87+
DataLayoutEntryListRef getEntries() const { return getDataLayoutSpec().getEntries(); }
88+
LogicalResult verifySpec(Location loc) {
89+
return getDataLayoutSpec().verifySpec(loc);
90+
}
91+
StringAttr getEndiannessIdentifier(MLIRContext *context) const {
92+
return getDataLayoutSpec().getEndiannessIdentifier(context);
93+
}
94+
StringAttr getDefaultMemorySpaceIdentifier(MLIRContext *context) const {
95+
return getDataLayoutSpec().getDefaultMemorySpaceIdentifier(context);
96+
}
97+
StringAttr getAllocaMemorySpaceIdentifier(MLIRContext *context) const {
98+
return getDataLayoutSpec().getAllocaMemorySpaceIdentifier(context);
99+
}
100+
StringAttr getManglingModeIdentifier(MLIRContext *context) const {
101+
return getDataLayoutSpec().getManglingModeIdentifier(context);
102+
}
103+
StringAttr getProgramMemorySpaceIdentifier(MLIRContext *context) const {
104+
return getDataLayoutSpec().getProgramMemorySpaceIdentifier(context);
105+
}
106+
StringAttr getGlobalMemorySpaceIdentifier(MLIRContext *context) const {
107+
return getDataLayoutSpec().getGlobalMemorySpaceIdentifier(context);
108+
}
109+
StringAttr getStackAlignmentIdentifier(MLIRContext *context) const {
110+
return getDataLayoutSpec().getStackAlignmentIdentifier(context);
111+
}
112+
StringAttr getFunctionPointerAlignmentIdentifier(MLIRContext *context) const {
113+
return getDataLayoutSpec().getFunctionPointerAlignmentIdentifier(context);
114+
}
115+
StringAttr getLegalIntWidthsIdentifier(MLIRContext *context) const {
116+
return getDataLayoutSpec().getLegalIntWidthsIdentifier(context);
117+
}
118+
::mlir::DataLayoutEntryList getSpecForType(TypeID type) const {
119+
return getDataLayoutSpec().getSpecForType(type);
120+
}
121+
::mlir::DataLayoutEntryInterface getSpecForIdentifier(StringAttr identifier) const {
122+
return getDataLayoutSpec().getSpecForIdentifier(identifier);
123+
}
124+
FailureOr<Attribute> query(DataLayoutEntryKey key) const {
125+
return getDataLayoutSpec().query(key);
126+
}
127+
}];
23128
}
24129

25130
//===----------------------------------------------------------------------===//
@@ -1241,69 +1346,6 @@ def LLVM_VScaleRangeAttr : LLVM_Attr<"VScaleRange", "vscale_range"> {
12411346
let assemblyFormat = "`<` struct(params) `>`";
12421347
}
12431348

1244-
//===----------------------------------------------------------------------===//
1245-
// TargetFeaturesAttr
1246-
//===----------------------------------------------------------------------===//
1247-
1248-
def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features">
1249-
{
1250-
let summary = "LLVM target features attribute";
1251-
1252-
let description = [{
1253-
Represents the LLVM target features as a list that can be checked within
1254-
passes/rewrites.
1255-
1256-
Example:
1257-
```mlir
1258-
#llvm.target_features<["+sme", "+sve", "+sme-f64f64"]>
1259-
```
1260-
1261-
Then within a pass or rewrite the features active at an op can be queried:
1262-
1263-
```c++
1264-
auto targetFeatures = LLVM::TargetFeaturesAttr::featuresAt(op);
1265-
1266-
if (!targetFeatures.contains("+sme-f64f64"))
1267-
return failure();
1268-
```
1269-
}];
1270-
1271-
let parameters = (ins OptionalArrayRefParameter<"StringAttr">:$features);
1272-
1273-
let builders = [
1274-
TypeBuilder<(ins "::llvm::StringRef":$features)>,
1275-
TypeBuilder<(ins "::llvm::ArrayRef<::llvm::StringRef>":$features)>
1276-
];
1277-
1278-
let extraClassDeclaration = [{
1279-
/// Checks if a feature is contained within the features list.
1280-
/// Note: Using a StringAttr allows doing pointer-comparisons.
1281-
bool contains(::mlir::StringAttr feature) const;
1282-
bool contains(::llvm::StringRef feature) const;
1283-
1284-
bool nullOrEmpty() const {
1285-
// Checks if this attribute is null, or the features are empty.
1286-
return !bool(*this) || getFeatures().empty();
1287-
}
1288-
1289-
/// Returns the list of features as an LLVM-compatible string.
1290-
std::string getFeaturesString() const;
1291-
1292-
/// Finds the target features on the parent FunctionOpInterface.
1293-
/// Note: This assumes the attribute name matches the return value of
1294-
/// `getAttributeName()`.
1295-
static TargetFeaturesAttr featuresAt(Operation* op);
1296-
1297-
/// Canonical name for this attribute within MLIR.
1298-
static constexpr StringLiteral getAttributeName() {
1299-
return StringLiteral("target_features");
1300-
}
1301-
}];
1302-
1303-
let assemblyFormat = "`<` `[` (`]`) : ($features^ `]`)? `>`";
1304-
let genVerifyDecl = 1;
1305-
}
1306-
13071349
//===----------------------------------------------------------------------===//
13081350
// UndefAttr
13091351
//===----------------------------------------------------------------------===//

mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
#ifndef MLIR_DIALECT_LLVMIR_LLVMATTRS_H_
1515
#define MLIR_DIALECT_LLVMIR_LLVMATTRS_H_
1616

17-
#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
17+
#include "llvm/MC/TargetRegistry.h"
18+
#include "llvm/Target/TargetMachine.h"
19+
#include "mlir/Interfaces/DataLayoutInterfaces.h"
1820
#include "mlir/IR/OpImplementation.h"
1921
#include <optional>
2022

@@ -94,6 +96,12 @@ using linkage::Linkage;
9496
} // namespace LLVM
9597
} // namespace mlir
9698

99+
// First obtain TargetFeaturesAttr definitions as it is used both an LLVMIR
100+
// interface and that interface and this attribute are turn required by another
101+
// LLVMIR attribute.
102+
#define GET_ATTRDEF_CLASSES
103+
#include "mlir/Dialect/LLVMIR/LLVMTargetFeaturesAttrDefs.h.inc"
104+
97105
#include "mlir/Dialect/LLVMIR/LLVMAttrInterfaces.h.inc"
98106

99107
#define GET_ATTRDEF_CLASSES

mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define LLVMIR_DIALECT
1111

1212
include "mlir/IR/DialectBase.td"
13+
include "mlir/IR/AttrTypeBase.td"
1314

1415
def LLVM_Dialect : Dialect {
1516
let name = "llvm";
@@ -123,4 +124,11 @@ def LLVM_Dialect : Dialect {
123124
}];
124125
}
125126

127+
class LLVM_Attr<string name, string attrMnemonic,
128+
list<Trait> traits = [],
129+
string baseCppClass = "::mlir::Attribute">
130+
: AttrDef<LLVM_Dialect, name, traits, baseCppClass> {
131+
let mnemonic = attrMnemonic;
132+
}
133+
126134
#endif // LLVMIR_DIALECT

mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define LLVMIR_INTERFACES
1515

1616
include "mlir/IR/OpBase.td"
17+
include "mlir/Interfaces/DataLayoutInterfaces.td"
1718

1819
def FastmathFlagsInterface : OpInterface<"FastmathFlagsInterface"> {
1920
let description = [{
@@ -568,4 +569,46 @@ def LLVM_DIRecursiveTypeAttrInterface
568569
];
569570
}
570571

572+
def LLVM_TargetAttrInterface
573+
: AttrInterface<"TargetAttrInterface", [DLTIQueryInterface]> {
574+
let description = [{
575+
TODO
576+
577+
NEEDS TO document which TI keys it responds to.
578+
}];
579+
let cppNamespace = "::mlir::LLVM";
580+
let methods = [
581+
InterfaceMethod<
582+
/*description=*/"Returns the target triple identifier.",
583+
/*retTy=*/"::llvm::StringRef",
584+
/*methodName=*/"getTriple",
585+
/*args=*/(ins)
586+
>,
587+
InterfaceMethod<
588+
/*description=*/"Returns the target cpu identifier.",
589+
/*retTy=*/"::llvm::StringRef",
590+
/*methodName=*/"getCpu",
591+
/*args=*/(ins)
592+
>,
593+
InterfaceMethod<
594+
/*description=*/"Returns the target features as a string.",
595+
/*retTy=*/"::mlir::LLVM::TargetFeaturesAttr",
596+
/*methodName=*/"getTargetFeatures",
597+
/*args=*/(ins)
598+
>,
599+
InterfaceMethod<
600+
/*description=*/"Returns the target machine.",
601+
/*retTy=*/"FailureOr<::llvm::TargetMachine *>",
602+
/*methodName=*/"getTargetMachine",
603+
/*args=*/(ins)
604+
>,
605+
InterfaceMethod<
606+
/*description=*/"Returns the data layout associated to the target machine.",
607+
/*retTy=*/"FailureOr<::llvm::DataLayout>",
608+
/*methodName=*/"getDataLayout",
609+
/*args=*/(ins)
610+
>
611+
];
612+
}
613+
571614
#endif // LLVMIR_INTERFACES

0 commit comments

Comments
 (0)