Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions flang/include/flang/Optimizer/Dialect/FIRType.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#ifndef FORTRAN_OPTIMIZER_DIALECT_FIRTYPE_H
#define FORTRAN_OPTIMIZER_DIALECT_FIRTYPE_H

#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/Interfaces/DataLayoutInterfaces.h"
Expand Down
18 changes: 16 additions & 2 deletions mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,26 @@ mlir_tablegen(LLVMOpsDialect.h.inc -gen-dialect-decls)
mlir_tablegen(LLVMOpsDialect.cpp.inc -gen-dialect-defs)
mlir_tablegen(LLVMOpsEnums.h.inc -gen-enum-decls)
mlir_tablegen(LLVMOpsEnums.cpp.inc -gen-enum-defs)
mlir_tablegen(LLVMOpsAttrDefs.h.inc -gen-attrdef-decls
-attrdefs-dialect=llvm)
#For LLVMOpsAttrDefs.h.inc, see below.
mlir_tablegen(LLVMOpsAttrDefs.cpp.inc -gen-attrdef-defs
-attrdefs-dialect=llvm)
add_public_tablegen_target(MLIRLLVMOpsIncGen)

# NB: Separate out LLVMOpsAttrDefs.h.inc generation as generating it
# through LLVMOps.td ends up defining LLVMTargetFeaturesAttr even
# though LLVMTargetFeaturesAttrDefs.* is responsible for that.
set(LLVM_TARGET_DEFINITIONS LLVMAttrAndEnumDefs.td)
mlir_tablegen(LLVMOpsAttrDefs.h.inc -gen-attrdef-decls -attrdefs-dialect=llvm)
add_public_tablegen_target(MLIRLLVMAttrsIncGen)

# NB: LLVMTargetFeaturesAttr is split out into its own file
# to break a recursive dependency: LLVMInterfaces depends
# on it, and other LLVMAttrs depending on LLVMInterfaces.
set(LLVM_TARGET_DEFINITIONS LLVMTargetFeaturesAttrDefs.td)
mlir_tablegen(LLVMTargetFeaturesAttrDefs.h.inc -gen-attrdef-decls)
mlir_tablegen(LLVMTargetFeaturesAttrDefs.cpp.inc -gen-attrdef-defs)
add_public_tablegen_target(MLIRLLVMTargetFeaturesAttrsIncGen)

set(LLVM_TARGET_DEFINITIONS LLVMTypes.td)
mlir_tablegen(LLVMTypes.h.inc -gen-typedef-decls -typedefs-dialect=llvm)
mlir_tablegen(LLVMTypes.cpp.inc -gen-typedef-defs -typedefs-dialect=llvm)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@
//
//===----------------------------------------------------------------------===//

#ifndef MLIR_LIB_TARGET_LLVMIR_DATALAYOUTIMPORTER_H_
#define MLIR_LIB_TARGET_LLVMIR_DATALAYOUTIMPORTER_H_
#ifndef MLIR_LLVMIR_DATALAYOUTIMPORTER_H_
#define MLIR_LLVMIR_DATALAYOUTIMPORTER_H_

#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/Interfaces/DataLayoutInterfaces.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/IR/DataLayout.h"

namespace llvm {
class StringRef;
Expand All @@ -38,6 +39,8 @@ namespace detail {
/// null if the bit width is not supported.
FloatType getFloatType(MLIRContext *context, unsigned width);

} // namespace detail

/// Helper class that translates an LLVM data layout to an MLIR data layout
/// specification. Only integer, float, pointer, alloca memory space, stack
/// alignment, and endianness entries are translated. The class also returns all
Expand All @@ -49,7 +52,21 @@ class DataLayoutImporter {
DataLayoutImporter(MLIRContext *context,
const llvm::DataLayout &llvmDataLayout)
: context(context) {
translateDataLayout(llvmDataLayout);
// Transform the data layout to its string representation and append the
// default data layout string specified in the language reference
// (https://llvm.org/docs/LangRef.html#data-layout). The translation then
// parses the string and ignores the default value if a specific kind occurs
// in both strings. Additionally, the following default values exist:
// - non-default address space pointer specifications default to the default
// address space pointer specification
// - the alloca address space defaults to the default address space.
layoutStr = llvmDataLayout.getStringRepresentation();
translateDataLayoutFromStr();
}

DataLayoutImporter(MLIRContext *context, StringRef dataLayoutStr)
: layoutStr(dataLayoutStr), context(context) {
translateDataLayoutFromStr();
}

/// Returns the MLIR data layout specification translated from the LLVM
Expand All @@ -66,7 +83,7 @@ class DataLayoutImporter {

private:
/// Translates the LLVM `dataLayout` to an MLIR data layout specification.
void translateDataLayout(const llvm::DataLayout &llvmDataLayout);
void translateDataLayoutFromStr();

/// Tries to parse the letter only prefix that identifies the specification
/// and removes the consumed characters from the beginning of the string.
Expand Down Expand Up @@ -125,8 +142,7 @@ class DataLayoutImporter {
DataLayoutSpecInterface dataLayout;
};

} // namespace detail
} // namespace LLVM
} // namespace mlir

#endif // MLIR_LIB_TARGET_LLVMIR_DATALAYOUTIMPORTER_H_
#endif // MLIR_LLVMIR_DATALAYOUTIMPORTER_H_
10 changes: 10 additions & 0 deletions mlir/include/mlir/Dialect/LLVMIR/LLVMAttrAndEnumDefs.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//===-- LLVMAttrDefs.td - Solely LLVM Attribute and Enum definitions ----*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

include "mlir/Dialect/LLVMIR/LLVMAttrDefs.td"
include "mlir/Dialect/LLVMIR/LLVMEnums.td"
200 changes: 131 additions & 69 deletions mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,138 @@ include "mlir/Dialect/LLVMIR/LLVMDialect.td"
include "mlir/Dialect/LLVMIR/LLVMInterfaces.td"
include "mlir/IR/AttrTypeBase.td"
include "mlir/IR/CommonAttrConstraints.td"
include "mlir/Interfaces/DataLayoutInterfaces.td"

// All of the attributes will extend this class.
class LLVM_Attr<string name, string attrMnemonic,
list<Trait> traits = [],
string baseCppClass = "::mlir::Attribute">
: AttrDef<LLVM_Dialect, name, traits, baseCppClass> {
let mnemonic = attrMnemonic;
//===----------------------------------------------------------------------===//
// LLVM_TargetAttr
//===----------------------------------------------------------------------===//

def LLVM_TargetAttr : LLVM_Attr<"Target", "target",
[LLVM_TargetAttrInterface]> {
let summary = "LLVM target info: triple, chip, features";
let description = [{
An attribute to hold LLVM target information, specifying LLVM's target
`triple` string, the target `chip` string (i.e. the `cpu` string), and
target `features` string as an attribute. The latter two are optional.

Has facilities to obtain the corresponding `llvm::TargetMachine` and
`llvm::DataLayout`, given the relevant LLVM backend is loaded.

---

Responds to DLTI-queries on the keys:
* A query for `"triple"` returns the `StringAttr` for the `triple`.
* A query for `"chip"` returns the `StringAttr` for the `chip`/`cpu`, if provided.
* A query for `"features"` returns the `TargetFeaturesAttr`, if provided.
* Individual features can be queried for on this attribute.
}];
let parameters = (ins "StringAttr":$triple,
OptionalParameter<"StringAttr">:$chip,
OptionalParameter<"TargetFeaturesAttr">:$features);

let assemblyFormat = [{`<` `triple` `=` $triple
(`,` `chip` `=` $chip^)?
(`,` qualified($features)^)? `>`}];

let extraClassDeclaration = [{
std::optional<llvm::TargetMachine *> targetMachine = std::nullopt;

FailureOr<llvm::TargetMachine *> getTargetMachine();

std::optional<llvm::DataLayout> dataLayout = std::nullopt;
FailureOr<llvm::DataLayout> getDataLayout();
FailureOr<Attribute> query(DataLayoutEntryKey key);
}];
}

//===----------------------------------------------------------------------===//
// LLVM_DataLayoutAttr
//===----------------------------------------------------------------------===//

def LLVM_DataLayoutAttr
: LLVM_Attr<"DataLayout", "data_layout", [DataLayoutSpecInterface]> {
let summary = "LLVM data layout string, exposed through DLTI";
let description = [{
An attribute to hold a LLVM data layout string.

The LLVM data layout string is parsed and mapped to the corresponding MLIR
data layout specification. The `#llvm.data_layout` attribute then serves as
a proxy, forwarding all DLTI queries to the underlying MLIR data layout
specification.
}];
let parameters = (ins "StringAttr":$data_layout_str,
OptionalParameter<"DataLayoutSpecInterface", "{}">:$data_layout_spec);
let builders = [
AttrBuilder<(ins "llvm::StringRef":$data_layout_str), [{
auto importer = LLVM::DataLayoutImporter($_ctxt, data_layout_str);
auto dataLayoutSpec = importer.getDataLayout();
return $_get($_ctxt, mlir::StringAttr::get($_ctxt, data_layout_str), dataLayoutSpec);
}]>
];
let assemblyFormat = "`<` $data_layout_str `>`";
let extraClassDeclaration = [{
template <typename Ty>
DataLayoutEntryList getSpecForType() {
return getDataLayoutSpec().getSpecForType(TypeID::get<Ty>());
}

inline ::mlir::FailureOr<::mlir::Attribute>
queryHelper(::mlir::DataLayoutEntryKey key) const {
return getDataLayoutSpec().queryHelper(key);
}

void bucketEntriesByType(
::llvm::MapVector<::mlir::TypeID, ::mlir::DataLayoutEntryList> &types,
::llvm::MapVector<::mlir::StringAttr,
::mlir::DataLayoutEntryInterface> &ids) {
getDataLayoutSpec().bucketEntriesByType(types, ids);
};

::mlir::DataLayoutSpecInterface
combineWith(ArrayRef<::mlir::DataLayoutSpecInterface> specs) const {
return getDataLayoutSpec().combineWith(specs);
}
DataLayoutEntryListRef getEntries() const { return getDataLayoutSpec().getEntries(); }
LogicalResult verifySpec(Location loc) {
return getDataLayoutSpec().verifySpec(loc);
}
StringAttr getEndiannessIdentifier(MLIRContext *context) const {
return getDataLayoutSpec().getEndiannessIdentifier(context);
}
StringAttr getDefaultMemorySpaceIdentifier(MLIRContext *context) const {
return getDataLayoutSpec().getDefaultMemorySpaceIdentifier(context);
}
StringAttr getAllocaMemorySpaceIdentifier(MLIRContext *context) const {
return getDataLayoutSpec().getAllocaMemorySpaceIdentifier(context);
}
StringAttr getManglingModeIdentifier(MLIRContext *context) const {
return getDataLayoutSpec().getManglingModeIdentifier(context);
}
StringAttr getProgramMemorySpaceIdentifier(MLIRContext *context) const {
return getDataLayoutSpec().getProgramMemorySpaceIdentifier(context);
}
StringAttr getGlobalMemorySpaceIdentifier(MLIRContext *context) const {
return getDataLayoutSpec().getGlobalMemorySpaceIdentifier(context);
}
StringAttr getStackAlignmentIdentifier(MLIRContext *context) const {
return getDataLayoutSpec().getStackAlignmentIdentifier(context);
}
StringAttr getFunctionPointerAlignmentIdentifier(MLIRContext *context) const {
return getDataLayoutSpec().getFunctionPointerAlignmentIdentifier(context);
}
StringAttr getLegalIntWidthsIdentifier(MLIRContext *context) const {
return getDataLayoutSpec().getLegalIntWidthsIdentifier(context);
}
::mlir::DataLayoutEntryList getSpecForType(TypeID type) const {
return getDataLayoutSpec().getSpecForType(type);
}
::mlir::DataLayoutEntryInterface getSpecForIdentifier(StringAttr identifier) const {
return getDataLayoutSpec().getSpecForIdentifier(identifier);
}
FailureOr<Attribute> query(DataLayoutEntryKey key) const {
return getDataLayoutSpec().query(key);
}
}];
}

//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -1241,69 +1366,6 @@ def LLVM_VScaleRangeAttr : LLVM_Attr<"VScaleRange", "vscale_range"> {
let assemblyFormat = "`<` struct(params) `>`";
}

//===----------------------------------------------------------------------===//
// TargetFeaturesAttr
//===----------------------------------------------------------------------===//

def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features">
{
let summary = "LLVM target features attribute";

let description = [{
Represents the LLVM target features as a list that can be checked within
passes/rewrites.

Example:
```mlir
#llvm.target_features<["+sme", "+sve", "+sme-f64f64"]>
```

Then within a pass or rewrite the features active at an op can be queried:

```c++
auto targetFeatures = LLVM::TargetFeaturesAttr::featuresAt(op);

if (!targetFeatures.contains("+sme-f64f64"))
return failure();
```
}];

let parameters = (ins OptionalArrayRefParameter<"StringAttr">:$features);

let builders = [
TypeBuilder<(ins "::llvm::StringRef":$features)>,
TypeBuilder<(ins "::llvm::ArrayRef<::llvm::StringRef>":$features)>
];

let extraClassDeclaration = [{
/// Checks if a feature is contained within the features list.
/// Note: Using a StringAttr allows doing pointer-comparisons.
bool contains(::mlir::StringAttr feature) const;
bool contains(::llvm::StringRef feature) const;

bool nullOrEmpty() const {
// Checks if this attribute is null, or the features are empty.
return !bool(*this) || getFeatures().empty();
}

/// Returns the list of features as an LLVM-compatible string.
std::string getFeaturesString() const;

/// Finds the target features on the parent FunctionOpInterface.
/// Note: This assumes the attribute name matches the return value of
/// `getAttributeName()`.
static TargetFeaturesAttr featuresAt(Operation* op);

/// Canonical name for this attribute within MLIR.
static constexpr StringLiteral getAttributeName() {
return StringLiteral("target_features");
}
}];

let assemblyFormat = "`<` `[` (`]`) : ($features^ `]`)? `>`";
let genVerifyDecl = 1;
}

//===----------------------------------------------------------------------===//
// UndefAttr
//===----------------------------------------------------------------------===//
Expand Down
12 changes: 10 additions & 2 deletions mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
#ifndef MLIR_DIALECT_LLVMIR_LLVMATTRS_H_
#define MLIR_DIALECT_LLVMIR_LLVMATTRS_H_

#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
#include "mlir/IR/OpImplementation.h"
#include "mlir/Interfaces/DataLayoutInterfaces.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Target/TargetMachine.h"
#include <optional>

#include "mlir/Dialect/LLVMIR/LLVMOpsEnums.h.inc"
Expand Down Expand Up @@ -89,11 +91,17 @@ class TBAANodeAttr : public Attribute {
// TODO: this shouldn't be needed after we unify the attribute generation, i.e.
// --gen-attr-* and --gen-attrdef-*.
using cconv::CConv;
using tailcallkind::TailCallKind;
using linkage::Linkage;
using tailcallkind::TailCallKind;
} // namespace LLVM
} // namespace mlir

// First obtain TargetFeaturesAttr definitions as it is used both an LLVMIR
// interface and that interface and this attribute are turn required by another
// LLVMIR attribute.
#define GET_ATTRDEF_CLASSES
#include "mlir/Dialect/LLVMIR/LLVMTargetFeaturesAttrDefs.h.inc"

#include "mlir/Dialect/LLVMIR/LLVMAttrInterfaces.h.inc"

#define GET_ATTRDEF_CLASSES
Expand Down
8 changes: 8 additions & 0 deletions mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define LLVMIR_DIALECT

include "mlir/IR/DialectBase.td"
include "mlir/IR/AttrTypeBase.td"

def LLVM_Dialect : Dialect {
let name = "llvm";
Expand Down Expand Up @@ -123,4 +124,11 @@ def LLVM_Dialect : Dialect {
}];
}

class LLVM_Attr<string name, string attrMnemonic,
list<Trait> traits = [],
string baseCppClass = "::mlir::Attribute">
: AttrDef<LLVM_Dialect, name, traits, baseCppClass> {
let mnemonic = attrMnemonic;
}

#endif // LLVMIR_DIALECT
Loading