[Mlir-commits] [mlir] [MLIR][LLVM][DLTI] Handle data layout token 'Fn32' (PR #141167)
Bruno Cardoso Lopes
llvmlistbot at llvm.org
Fri May 23 10:51:22 PDT 2025
https://github.com/bcardosolopes updated https://github.com/llvm/llvm-project/pull/141167
>From 7c05f1f22f80d111e00964f7d9c0a2c268730836 Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Thu, 22 May 2025 10:52:38 -0700
Subject: [PATCH 1/4] [MLIR][LLVM][DLTI] Handle data layout token 'Fn32'
---
mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td | 34 ++++++++++++++++++
mlir/include/mlir/Dialect/DLTI/DLTIBase.td | 5 ++-
.../mlir/Interfaces/DataLayoutInterfaces.h | 12 +++++++
.../mlir/Interfaces/DataLayoutInterfaces.td | 18 ++++++++++
mlir/lib/Dialect/DLTI/DLTI.cpp | 7 ++++
mlir/lib/Interfaces/DataLayoutInterfaces.cpp | 27 ++++++++++++++
mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp | 36 +++++++++++++++++++
mlir/lib/Target/LLVMIR/DataLayoutImporter.h | 5 +++
mlir/lib/Target/LLVMIR/ModuleTranslation.cpp | 10 ++++++
mlir/test/Dialect/LLVMIR/layout.mlir | 18 +++++++++-
mlir/test/Target/LLVMIR/Import/data-layout.ll | 3 +-
mlir/test/Target/LLVMIR/data-layout.mlir | 8 ++++-
.../lib/Dialect/DLTI/TestDataLayoutQuery.cpp | 12 ++++++-
.../Interfaces/DataLayoutInterfacesTest.cpp | 13 ++++++-
14 files changed, 202 insertions(+), 6 deletions(-)
diff --git a/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td b/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td
index cf3a72633587d..d53fbe3a60fa6 100644
--- a/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td
+++ b/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td
@@ -92,6 +92,9 @@ def DLTI_DataLayoutSpecAttr :
/// Returns the stack alignment identifier.
StringAttr getStackAlignmentIdentifier(MLIRContext *context) const;
+ /// Returns the function poinrter alignment identifier.
+ StringAttr getFunctionPointerAlignmentIdentifier(MLIRContext *context) const;
+
/// Returns the attribute associated with the key.
FailureOr<Attribute> query(DataLayoutEntryKey key) {
return ::llvm::cast<mlir::DataLayoutSpecInterface>(*this).queryHelper(key);
@@ -249,4 +252,35 @@ def DLTI_TargetDeviceSpecAttr :
}];
}
+//===----------------------------------------------------------------------===//
+// FunctionPointerAlignmentAttr
+//===----------------------------------------------------------------------===//
+
+def DLTI_FunctionPointerAlignmentAttr :
+ DLTIAttr<"FunctionPointerAlignment", []> {
+ let summary = "An attribute to represent function pointer alignment.";
+ let description = [{
+ Function pointer alignment specifies the minimum alignment of function
+ pointers, it's a multiple of `alignment`. This alignment can also depend
+ on the target function, indicated by `function_dependent`.
+ Example:
+ ```
+ #dlti.dl_entry<"dlti.function_pointer_alignment",
+ #dlti.function_pointer_alignment<64, function_dependent = false>>
+ ```
+ }];
+ let parameters = (ins
+ "uint64_t":$alignment,
+ "bool":$function_dependent
+ );
+ let assemblyFormat = [{
+ `<`
+ $alignment `,`
+ `function_dependent` `=` $function_dependent
+ `>`
+ }];
+ let mnemonic = "function_pointer_alignment";
+}
+
+
#endif // MLIR_DIALECT_DLTI_DLTIATTRS_TD
diff --git a/mlir/include/mlir/Dialect/DLTI/DLTIBase.td b/mlir/include/mlir/Dialect/DLTI/DLTIBase.td
index 1a08bafda54ee..ad5f9dc611c79 100644
--- a/mlir/include/mlir/Dialect/DLTI/DLTIBase.td
+++ b/mlir/include/mlir/Dialect/DLTI/DLTIBase.td
@@ -58,7 +58,7 @@ def DLTI_Dialect : Dialect {
constexpr const static ::llvm::StringLiteral
kDataLayoutAllocaMemorySpaceKey = "dlti.alloca_memory_space";
-
+
constexpr const static ::llvm::StringLiteral
kDataLayoutProgramMemorySpaceKey = "dlti.program_memory_space";
@@ -67,6 +67,9 @@ def DLTI_Dialect : Dialect {
constexpr const static ::llvm::StringLiteral
kDataLayoutStackAlignmentKey = "dlti.stack_alignment";
+
+ constexpr const static ::llvm::StringLiteral
+ kDataLayoutFunctionPointerAlignmentKey = "dlti.function_pointer_alignment";
}];
let useDefaultAttributePrinterParser = 1;
diff --git a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h
index ff40bfc4bee41..89ae6d8877f14 100644
--- a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h
+++ b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h
@@ -101,6 +101,10 @@ Attribute getDefaultGlobalMemorySpace(DataLayoutEntryInterface entry);
/// DataLayoutInterface if specified, otherwise returns the default.
uint64_t getDefaultStackAlignment(DataLayoutEntryInterface entry);
+/// Default handler for the stack alignment request. Dispatches to the
+/// DataLayoutInterface if specified, otherwise returns the default.
+Attribute getDefaultFunctionPointerAlignment(DataLayoutEntryInterface entry);
+
/// Returns the value of the property from the specified DataLayoutEntry. If the
/// property is missing from the entry, returns std::nullopt.
std::optional<Attribute> getDevicePropertyValue(DataLayoutEntryInterface entry);
@@ -259,6 +263,12 @@ class DataLayout {
/// unspecified.
uint64_t getStackAlignment() const;
+ /// Returns the natural alignment of the stack in bits. Alignment promotion of
+ /// stack variables should be limited to the natural stack alignment to
+ /// prevent dynamic stack alignment. Returns zero if the stack alignment is
+ /// unspecified.
+ Attribute getFunctionPointerAlignment() const;
+
/// Returns the value of the specified property if the property is defined for
/// the given device ID, otherwise returns std::nullopt.
std::optional<Attribute>
@@ -303,6 +313,8 @@ class DataLayout {
/// Cache for stack alignment.
mutable std::optional<uint64_t> stackAlignment;
+ /// Cache for function pointer alignment.
+ mutable std::optional<Attribute> functionPointerAlignment;
};
} // namespace mlir
diff --git a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td
index c5973d4252b0a..d10a2fd9dc8e4 100644
--- a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td
+++ b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td
@@ -171,6 +171,12 @@ def DataLayoutSpecInterface : AttrInterface<"DataLayoutSpecInterface", [DLTIQuer
/*methodName=*/"getStackAlignmentIdentifier",
/*args=*/(ins "::mlir::MLIRContext *":$context)
>,
+ InterfaceMethod<
+ /*description=*/"Returns the function pointer alignment identifier.",
+ /*retTy=*/"::mlir::StringAttr",
+ /*methodName=*/"getFunctionPointerAlignmentIdentifier",
+ /*args=*/(ins "::mlir::MLIRContext *":$context)
+ >,
// Implementations may override this if they have an efficient lookup
// mechanism.
InterfaceMethod<
@@ -553,6 +559,18 @@ def DataLayoutOpInterface : OpInterface<"DataLayoutOpInterface"> {
return ::mlir::detail::getDefaultStackAlignment(entry);
}]
>,
+ StaticInterfaceMethod<
+ /*description=*/"Returns the function pointer alignment in bits computed "
+ "using the relevant entries. The data layout object "
+ "can be used for recursive queries.",
+ /*retTy=*/"Attribute",
+ /*methodName=*/"getFunctionPointerAlignment",
+ /*args=*/(ins "::mlir::DataLayoutEntryInterface":$entry),
+ /*methodBody=*/"",
+ /*defaultImplementation=*/[{
+ return ::mlir::detail::getDefaultFunctionPointerAlignment(entry);
+ }]
+ >,
StaticInterfaceMethod<
/*description=*/"Returns the value of the property, if the property is "
"defined. Otherwise, it returns std::nullopt.",
diff --git a/mlir/lib/Dialect/DLTI/DLTI.cpp b/mlir/lib/Dialect/DLTI/DLTI.cpp
index 5d7dd2f8443df..ae8f016c3d1a5 100644
--- a/mlir/lib/Dialect/DLTI/DLTI.cpp
+++ b/mlir/lib/Dialect/DLTI/DLTI.cpp
@@ -420,6 +420,12 @@ DataLayoutSpecAttr::getStackAlignmentIdentifier(MLIRContext *context) const {
DLTIDialect::kDataLayoutStackAlignmentKey);
}
+StringAttr DataLayoutSpecAttr::getFunctionPointerAlignmentIdentifier(
+ MLIRContext *context) const {
+ return Builder(context).getStringAttr(
+ DLTIDialect::kDataLayoutFunctionPointerAlignmentKey);
+}
+
/// Parses an attribute with syntax:
/// dl-spec-attr ::= `#dlti.` `dl_spec` `<` entry-list `>`
/// entry-list ::= | entry | entry `,` entry-list
@@ -625,6 +631,7 @@ class TargetDataLayoutInterface : public DataLayoutDialectInterface {
entryName == DLTIDialect::kDataLayoutProgramMemorySpaceKey ||
entryName == DLTIDialect::kDataLayoutGlobalMemorySpaceKey ||
entryName == DLTIDialect::kDataLayoutStackAlignmentKey ||
+ entryName == DLTIDialect::kDataLayoutFunctionPointerAlignmentKey ||
entryName == DLTIDialect::kDataLayoutManglingModeKey)
return success();
return emitError(loc) << "unknown data layout entry name: " << entryName;
diff --git a/mlir/lib/Interfaces/DataLayoutInterfaces.cpp b/mlir/lib/Interfaces/DataLayoutInterfaces.cpp
index 4ac66c3107384..839db6d718dd5 100644
--- a/mlir/lib/Interfaces/DataLayoutInterfaces.cpp
+++ b/mlir/lib/Interfaces/DataLayoutInterfaces.cpp
@@ -312,6 +312,16 @@ mlir::detail::getDefaultStackAlignment(DataLayoutEntryInterface entry) {
return value.getValue().getZExtValue();
}
+// Returns the function pointer alignment if specified in the given entry. If
+// the entry is empty the default alignment zero is returned.
+Attribute mlir::detail::getDefaultFunctionPointerAlignment(
+ DataLayoutEntryInterface entry) {
+ if (entry == DataLayoutEntryInterface()) {
+ return Attribute();
+ }
+ return entry.getValue();
+}
+
std::optional<Attribute>
mlir::detail::getDevicePropertyValue(DataLayoutEntryInterface entry) {
if (entry == DataLayoutEntryInterface())
@@ -710,6 +720,23 @@ uint64_t mlir::DataLayout::getStackAlignment() const {
return *stackAlignment;
}
+Attribute mlir::DataLayout::getFunctionPointerAlignment() const {
+ checkValid();
+ if (functionPointerAlignment)
+ return *functionPointerAlignment;
+ DataLayoutEntryInterface entry;
+ if (originalLayout)
+ entry = originalLayout.getSpecForIdentifier(
+ originalLayout.getFunctionPointerAlignmentIdentifier(
+ originalLayout.getContext()));
+ if (auto iface = dyn_cast_or_null<DataLayoutOpInterface>(scope))
+ functionPointerAlignment = iface.getFunctionPointerAlignment(entry);
+ else
+ functionPointerAlignment =
+ detail::getDefaultFunctionPointerAlignment(entry);
+ return *functionPointerAlignment;
+}
+
std::optional<Attribute> mlir::DataLayout::getDevicePropertyValue(
TargetSystemSpecInterface::DeviceID deviceID,
StringAttr propertyName) const {
diff --git a/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp b/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
index a5307d8e4c1ab..4e0ecfc8401a7 100644
--- a/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
+++ b/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
@@ -221,6 +221,34 @@ DataLayoutImporter::tryToEmplaceStackAlignmentEntry(StringRef token) {
return success();
}
+LogicalResult DataLayoutImporter::tryToEmplaceFunctionPointerAlignmentEntry(
+ StringRef fnPtrString, StringRef token) {
+ auto key = StringAttr::get(
+ context, DLTIDialect::kDataLayoutFunctionPointerAlignmentKey);
+ if (keyEntries.count(key))
+ return success();
+
+ // i: The alignment of function pointers is independent of the alignment of
+ // functions, and is a multiple of <abi>.
+ // n: The alignment of function pointers is a multiple of the explicit
+ // alignment specified on the function, and is a multiple of <abi>.
+ bool functionDependent = false;
+ if (fnPtrString == "n")
+ functionDependent = true;
+ else if (fnPtrString != "i")
+ return failure();
+
+ FailureOr<uint64_t> alignment = tryToParseInt(token);
+ if (failed(alignment))
+ return failure();
+
+ keyEntries.try_emplace(
+ key, DataLayoutEntryAttr::get(
+ key, FunctionPointerAlignmentAttr::get(
+ key.getContext(), *alignment, functionDependent)));
+ return success();
+}
+
void DataLayoutImporter::translateDataLayout(
const llvm::DataLayout &llvmDataLayout) {
dataLayout = {};
@@ -330,6 +358,14 @@ void DataLayoutImporter::translateDataLayout(
return;
continue;
}
+ // Parse function pointer alignment specifications.
+ // Note that prefix here is "Fn" or "Fi", not a single character.
+ if (prefix->starts_with("F")) {
+ StringRef nextPrefix = prefix->drop_front(1);
+ if (failed(tryToEmplaceFunctionPointerAlignmentEntry(nextPrefix, token)))
+ return;
+ continue;
+ }
// Store all tokens that have not been handled.
unhandledTokens.push_back(lastToken);
diff --git a/mlir/lib/Target/LLVMIR/DataLayoutImporter.h b/mlir/lib/Target/LLVMIR/DataLayoutImporter.h
index 491ff65f17a41..501cff89d4738 100644
--- a/mlir/lib/Target/LLVMIR/DataLayoutImporter.h
+++ b/mlir/lib/Target/LLVMIR/DataLayoutImporter.h
@@ -108,6 +108,11 @@ class DataLayoutImporter {
/// Adds a stack alignment entry if there is none yet.
LogicalResult tryToEmplaceStackAlignmentEntry(StringRef token);
+ /// Adds a function pointer alignment entry if there is none yet.
+ LogicalResult
+ tryToEmplaceFunctionPointerAlignmentEntry(StringRef fnPtrAlignEntry,
+ StringRef token);
+
std::string layoutStr = {};
StringRef lastToken = {};
SmallVector<StringRef> unhandledTokens;
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 9b5c93171abfd..047e870b7dcd8 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -240,6 +240,16 @@ translateDataLayout(DataLayoutSpecInterface attribute,
layoutStream << "-S" << alignment;
continue;
}
+ if (key.getValue() == DLTIDialect::kDataLayoutFunctionPointerAlignmentKey) {
+ auto value = cast<FunctionPointerAlignmentAttr>(entry.getValue());
+ uint64_t alignment = value.getAlignment();
+ // Skip the default function pointer alignment.
+ if (alignment == 0)
+ continue;
+ layoutStream << "-F" << (value.getFunctionDependent() ? "n" : "i")
+ << alignment;
+ continue;
+ }
emitError(*loc) << "unsupported data layout key " << key;
return failure();
}
diff --git a/mlir/test/Dialect/LLVMIR/layout.mlir b/mlir/test/Dialect/LLVMIR/layout.mlir
index 4e60f991f1bf5..d7392deea67bc 100644
--- a/mlir/test/Dialect/LLVMIR/layout.mlir
+++ b/mlir/test/Dialect/LLVMIR/layout.mlir
@@ -8,6 +8,8 @@ module {
// CHECK: bitsize = 64
// CHECK: default_memory_space = 0
// CHECK: endianness = ""
+ // CHECK: function_pointer_alignment =
+ // CHECK-SAME: #dlti.function_pointer_alignment<0, function_dependent = false>,
// CHECK: global_memory_space = 0
// CHECK: index = 64
// CHECK: mangling_mode = ""
@@ -21,6 +23,8 @@ module {
// CHECK: bitsize = 64
// CHECK: default_memory_space = 0
// CHECK: endianness = ""
+ // CHECK: function_pointer_alignment =
+ // CHECK-SAME: #dlti.function_pointer_alignment<0, function_dependent = false>,
// CHECK: global_memory_space = 0
// CHECK: index = 64
// CHECK: mangling_mode = ""
@@ -34,6 +38,8 @@ module {
// CHECK: bitsize = 64
// CHECK: default_memory_space = 0
// CHECK: endianness = ""
+ // CHECK: function_pointer_alignment =
+ // CHECK-SAME: #dlti.function_pointer_alignment<0, function_dependent = false>,
// CHECK: global_memory_space = 0
// CHECK: index = 64
// CHECK: mangling_mode = ""
@@ -58,7 +64,9 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<"dlti.global_memory_space", 2 : ui64>,
#dlti.dl_entry<"dlti.program_memory_space", 3 : ui64>,
#dlti.dl_entry<"dlti.stack_alignment", 128 : i64>,
- #dlti.dl_entry<"dlti.mangling_mode", "e">
+ #dlti.dl_entry<"dlti.mangling_mode", "e">,
+ #dlti.dl_entry<"dlti.function_pointer_alignment",
+ "#dlti.function_pointer_alignment<32, function_dependent = true>">
>} {
// CHECK: @spec
func.func @spec() {
@@ -67,6 +75,8 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
// CHECK: bitsize = 32
// CHECK: default_memory_space = 7
// CHECK: endianness = "little"
+ // CHECK: function_pointer_alignment =
+ // CHECK-SAME: "#dlti.function_pointer_alignment<32, function_dependent = true>",
// CHECK: global_memory_space = 2
// CHECK: index = 32
// CHECK: mangling_mode = "e"
@@ -80,6 +90,8 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
// CHECK: bitsize = 32
// CHECK: default_memory_space = 7
// CHECK: endianness = "little"
+ // CHECK: function_pointer_alignment =
+ // CHECK-SAME: "#dlti.function_pointer_alignment<32, function_dependent = true>",
// CHECK: global_memory_space = 2
// CHECK: index = 32
// CHECK: preferred = 8
@@ -92,6 +104,8 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
// CHECK: bitsize = 64
// CHECK: default_memory_space = 7
// CHECK: endianness = "little"
+ // CHECK: function_pointer_alignment =
+ // CHECK-SAME: "#dlti.function_pointer_alignment<32, function_dependent = true>",
// CHECK: global_memory_space = 2
// CHECK: index = 64
// CHECK: mangling_mode = "e"
@@ -105,6 +119,8 @@ module attributes { dlti.dl_spec = #dlti.dl_spec<
// CHECK: bitsize = 32
// CHECK: default_memory_space = 7
// CHECK: endianness = "little"
+ // CHECK: function_pointer_alignment =
+ // CHECK-SAME: "#dlti.function_pointer_alignment<32, function_dependent = true>",
// CHECK: global_memory_space = 2
// CHECK: index = 24
// CHECK: mangling_mode = "e"
diff --git a/mlir/test/Target/LLVMIR/Import/data-layout.ll b/mlir/test/Target/LLVMIR/Import/data-layout.ll
index d6f7719b3ca01..55e3f4dea5ff4 100644
--- a/mlir/test/Target/LLVMIR/Import/data-layout.ll
+++ b/mlir/test/Target/LLVMIR/Import/data-layout.ll
@@ -30,7 +30,8 @@ target datalayout = ""
; CHECK-SAME: "dlti.endianness" = "little"
; CHECK-SAME: "dlti.mangling_mode" = "e"
; CHECK-SAME: "dlti.stack_alignment" = 128 : i64
-target datalayout = "e-m:e-p270:32:64-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+; CHECK-SAME: "dlti.function_pointer_alignment" = #dlti.function_pointer_alignment<32, function_dependent = true>
+target datalayout = "e-m:e-p270:32:64-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128-Fn32"
; // -----
diff --git a/mlir/test/Target/LLVMIR/data-layout.mlir b/mlir/test/Target/LLVMIR/data-layout.mlir
index 3576461cd01f1..30b9b03de3dbb 100644
--- a/mlir/test/Target/LLVMIR/data-layout.mlir
+++ b/mlir/test/Target/LLVMIR/data-layout.mlir
@@ -5,6 +5,7 @@
// CHECK: A4-
// CHECK: S128-
// CHECK: m:e-
+// CHECK: Fn32
// CHECK: i64:64:128
// CHECK: f80:128:256
// CHECK: p0:32:64:128:32
@@ -14,6 +15,8 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<"dlti.alloca_memory_space", 4 : ui32>,
#dlti.dl_entry<"dlti.stack_alignment", 128 : i32>,
#dlti.dl_entry<"dlti.mangling_mode", "e">,
+#dlti.dl_entry<"dlti.function_pointer_alignment",
+ #dlti.function_pointer_alignment<32, function_dependent = true>>,
#dlti.dl_entry<index, 64>,
#dlti.dl_entry<i64, dense<[64,128]> : vector<2xi64>>,
#dlti.dl_entry<f80, dense<[128,256]> : vector<2xi64>>,
@@ -29,12 +32,15 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<
// CHECK: target datalayout
// CHECK: e
+// CHECK: Fi64
// CHECK-NOT: A0
// CHECK-NOT: S0
module attributes {dlti.dl_spec = #dlti.dl_spec<
#dlti.dl_entry<"dlti.endianness", "little">,
#dlti.dl_entry<"dlti.alloca_memory_space", 0 : ui32>,
-#dlti.dl_entry<"dlti.stack_alignment", 0 : i32>
+#dlti.dl_entry<"dlti.stack_alignment", 0 : i32>,
+#dlti.dl_entry<"dlti.function_pointer_alignment",
+ #dlti.function_pointer_alignment<64, function_dependent = false>>
>} {
llvm.func @bar() {
llvm.return
diff --git a/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp b/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp
index 41a2fe5e4ee75..08c8042f71a95 100644
--- a/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp
+++ b/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp
@@ -48,6 +48,7 @@ struct TestDataLayoutQuery
Attribute programMemorySpace = layout.getProgramMemorySpace();
Attribute globalMemorySpace = layout.getGlobalMemorySpace();
uint64_t stackAlignment = layout.getStackAlignment();
+ Attribute functionPointerAlignment = layout.getFunctionPointerAlignment();
auto convertTypeSizeToAttr = [&](llvm::TypeSize typeSize) -> Attribute {
if (!typeSize.isScalable())
@@ -90,7 +91,16 @@ struct TestDataLayoutQuery
? builder.getUI32IntegerAttr(0)
: globalMemorySpace),
builder.getNamedAttr("stack_alignment",
- builder.getIndexAttr(stackAlignment))});
+ builder.getIndexAttr(stackAlignment)),
+ builder.getNamedAttr("function_pointer_alignment",
+ functionPointerAlignment == Attribute()
+ ? FunctionPointerAlignmentAttr::get(
+ builder.getContext(), 0,
+ /*function_dependent=*/false)
+ : functionPointerAlignment)
+
+ });
+
});
}
};
diff --git a/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp b/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp
index fd81f3021aa9b..48bc2076055f8 100644
--- a/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp
+++ b/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp
@@ -35,6 +35,8 @@ constexpr static llvm::StringLiteral kGlobalKeyName =
"dltest.global_memory_space";
constexpr static llvm::StringLiteral kStackAlignmentKeyName =
"dltest.stack_alignment";
+constexpr static llvm::StringLiteral kFunctionPointerAlignmentKeyName =
+ "dltest.function_pointer_alignment";
constexpr static llvm::StringLiteral kTargetSystemDescAttrName =
"dl_target_sys_desc_test.target_system_spec";
@@ -102,6 +104,9 @@ struct CustomDataLayoutSpec
StringAttr getStackAlignmentIdentifier(MLIRContext *context) const {
return Builder(context).getStringAttr(kStackAlignmentKeyName);
}
+ StringAttr getFunctionPointerAlignmentIdentifier(MLIRContext *context) const {
+ return Builder(context).getStringAttr(kFunctionPointerAlignmentKeyName);
+ }
FailureOr<Attribute> query(DataLayoutEntryKey key) const {
return llvm::cast<mlir::DataLayoutSpecInterface>(*this).queryHelper(key);
}
@@ -494,6 +499,7 @@ module {}
EXPECT_EQ(layout.getProgramMemorySpace(), Attribute());
EXPECT_EQ(layout.getGlobalMemorySpace(), Attribute());
EXPECT_EQ(layout.getStackAlignment(), 0u);
+ EXPECT_EQ(layout.getFunctionPointerAlignment(), Attribute());
EXPECT_EQ(layout.getManglingMode(), Attribute());
}
@@ -594,7 +600,9 @@ TEST(DataLayout, SpecWithEntries) {
#dlti.dl_entry<"dltest.program_memory_space", 3 : i32>,
#dlti.dl_entry<"dltest.global_memory_space", 2 : i32>,
#dlti.dl_entry<"dltest.stack_alignment", 128 : i32>,
- #dlti.dl_entry<"dltest.mangling_mode", "o">
+ #dlti.dl_entry<"dltest.mangling_mode", "o">,
+ #dlti.dl_entry<"dltest.function_pointer_alignment",
+ #dlti.function_pointer_alignment<64, function_dependent = true>>
> } : () -> ()
)MLIR";
@@ -633,6 +641,9 @@ TEST(DataLayout, SpecWithEntries) {
EXPECT_EQ(layout.getGlobalMemorySpace(), Builder(&ctx).getI32IntegerAttr(2));
EXPECT_EQ(layout.getStackAlignment(), 128u);
EXPECT_EQ(layout.getManglingMode(), Builder(&ctx).getStringAttr("o"));
+ EXPECT_EQ(
+ layout.getFunctionPointerAlignment(),
+ FunctionPointerAlignmentAttr::get(&ctx, 64, /*function_dependent=*/true));
}
TEST(DataLayout, SpecWithTargetSystemDescEntries) {
>From 0acf751d5f04ef5dcfbfc8d90ab557a375c36327 Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Thu, 22 May 2025 17:32:43 -0700
Subject: [PATCH 2/4] Fix comments
---
mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td | 2 +-
mlir/include/mlir/Interfaces/DataLayoutInterfaces.h | 5 +----
mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp | 10 ++++++----
3 files changed, 8 insertions(+), 9 deletions(-)
diff --git a/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td b/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td
index d53fbe3a60fa6..2aa58ea014caa 100644
--- a/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td
+++ b/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td
@@ -92,7 +92,7 @@ def DLTI_DataLayoutSpecAttr :
/// Returns the stack alignment identifier.
StringAttr getStackAlignmentIdentifier(MLIRContext *context) const;
- /// Returns the function poinrter alignment identifier.
+ /// Returns the function pointer alignment identifier.
StringAttr getFunctionPointerAlignmentIdentifier(MLIRContext *context) const;
/// Returns the attribute associated with the key.
diff --git a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h
index 89ae6d8877f14..50f75c1ad9d40 100644
--- a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h
+++ b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h
@@ -263,10 +263,7 @@ class DataLayout {
/// unspecified.
uint64_t getStackAlignment() const;
- /// Returns the natural alignment of the stack in bits. Alignment promotion of
- /// stack variables should be limited to the natural stack alignment to
- /// prevent dynamic stack alignment. Returns zero if the stack alignment is
- /// unspecified.
+ /// Returns function pointer alignment.
Attribute getFunctionPointerAlignment() const;
/// Returns the value of the specified property if the property is defined for
diff --git a/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp b/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
index 4e0ecfc8401a7..1fc36d24094bd 100644
--- a/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
+++ b/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
@@ -228,10 +228,12 @@ LogicalResult DataLayoutImporter::tryToEmplaceFunctionPointerAlignmentEntry(
if (keyEntries.count(key))
return success();
- // i: The alignment of function pointers is independent of the alignment of
- // functions, and is a multiple of <abi>.
- // n: The alignment of function pointers is a multiple of the explicit
- // alignment specified on the function, and is a multiple of <abi>.
+ // The data layout entry for "F<type><abi>". <abi> is the aligment value,
+ // preceded by one of the two possible <types>:
+ // "i": The alignment of function pointers is independent of the alignment of
+ // functions, and is a multiple of <abi>.
+ // "n": The alignment of function pointers is a multiple of the explicit
+ // alignment specified on the function, and is a multiple of <abi>.
bool functionDependent = false;
if (fnPtrString == "n")
functionDependent = true;
>From 77f5e70d9d9bb1bd6e3bb14b5291d882e62eeae2 Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Thu, 22 May 2025 17:45:58 -0700
Subject: [PATCH 3/4] Add one more test
---
mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp b/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp
index 48bc2076055f8..ea173cdad7cce 100644
--- a/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp
+++ b/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp
@@ -577,6 +577,7 @@ TEST(DataLayout, EmptySpec) {
EXPECT_EQ(layout.getGlobalMemorySpace(), Attribute());
EXPECT_EQ(layout.getStackAlignment(), 0u);
EXPECT_EQ(layout.getManglingMode(), Attribute());
+ EXPECT_EQ(layout.getFunctionPointerAlignment(), Attribute());
EXPECT_EQ(layout.getDevicePropertyValue(
Builder(&ctx).getStringAttr("CPU" /* device ID*/),
>From b71db67dc557dd72cc3a600bd2b905adfa2c93b3 Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Fri, 23 May 2025 10:48:58 -0700
Subject: [PATCH 4/4] address reviews
---
mlir/include/mlir/Interfaces/DataLayoutInterfaces.h | 4 ++--
mlir/lib/Interfaces/DataLayoutInterfaces.cpp | 3 +--
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h
index 50f75c1ad9d40..55d169df1c009 100644
--- a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h
+++ b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h
@@ -101,8 +101,8 @@ Attribute getDefaultGlobalMemorySpace(DataLayoutEntryInterface entry);
/// DataLayoutInterface if specified, otherwise returns the default.
uint64_t getDefaultStackAlignment(DataLayoutEntryInterface entry);
-/// Default handler for the stack alignment request. Dispatches to the
-/// DataLayoutInterface if specified, otherwise returns the default.
+/// Default handler for the function pointer alignment request. Dispatches to
+/// the DataLayoutInterface if specified, otherwise returns the default.
Attribute getDefaultFunctionPointerAlignment(DataLayoutEntryInterface entry);
/// Returns the value of the property from the specified DataLayoutEntry. If the
diff --git a/mlir/lib/Interfaces/DataLayoutInterfaces.cpp b/mlir/lib/Interfaces/DataLayoutInterfaces.cpp
index 839db6d718dd5..fbbe28ce9b4cc 100644
--- a/mlir/lib/Interfaces/DataLayoutInterfaces.cpp
+++ b/mlir/lib/Interfaces/DataLayoutInterfaces.cpp
@@ -316,9 +316,8 @@ mlir::detail::getDefaultStackAlignment(DataLayoutEntryInterface entry) {
// the entry is empty the default alignment zero is returned.
Attribute mlir::detail::getDefaultFunctionPointerAlignment(
DataLayoutEntryInterface entry) {
- if (entry == DataLayoutEntryInterface()) {
+ if (entry == DataLayoutEntryInterface())
return Attribute();
- }
return entry.getValue();
}
More information about the Mlir-commits
mailing list