Skip to content

Commit 5d2bbe9

Browse files
[mlir][Func] Extract datalayout string attribute setting as a separate module pass
FuncToLLVM uses the data layout string attribute in 3 different ways: 1. LowerToLLVMOptions options(&getContext(), getAnalysis<DataLayoutAnalysis>().getAtOrAbove(m)); 2. options.dataLayout = llvm::DataLayout(this->dataLayout); 3. m->setAttr(..., this->dataLayout)); The 3rd way is unrelated to the other 2 and occurs after conversion, making it confusing. This revision separates this post-hoc module annotation functionality into its own pass. The convert-func-to-llvm pass loses its `data-layout` option and instead recovers it from the `llvm.data_layout` attribute attached to the module, when present. In the future, `LowerToLLVMOptions options(&getContext(), getAnalysis<DataLayoutAnalysis>().getAtOrAbove(m))` and `options.dataLayout = llvm::DataLayout(dataLayout);` should be unified. Reviewed By: ftynse, mehdi_amini Differential Revision: https://reviews.llvm.org/D157604
1 parent e6d305e commit 5d2bbe9

File tree

4 files changed

+53
-9
lines changed

4 files changed

+53
-9
lines changed

mlir/include/mlir/Conversion/FuncToLLVM/ConvertFuncToLLVMPass.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ namespace mlir {
1616
class Pass;
1717

1818
#define GEN_PASS_DECL_CONVERTFUNCTOLLVMPASS
19+
#define GEN_PASS_DECL_SETLLVMMODULEDATALAYOUTPASS
1920
#include "mlir/Conversion/Passes.h.inc"
2021

2122
} // namespace mlir

mlir/include/mlir/Conversion/Passes.td

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,21 @@ def ConvertControlFlowToSPIRV : Pass<"convert-cf-to-spirv"> {
341341
// FuncToLLVM
342342
//===----------------------------------------------------------------------===//
343343

344+
def SetLLVMModuleDataLayoutPass : Pass<"set-llvm-module-datalayout", "ModuleOp"> {
345+
let summary = "Attach a datalayout string as a module attribute";
346+
let description = [{
347+
Verify that the dataLayout string is a valid LLVM datalayout string and
348+
attach it as an attribute `LLVMDialect::getDataLayoutAttrName()` to the
349+
module, overriding the existing one.
350+
}];
351+
let options = [
352+
Option<"dataLayout", "data-layout", "std::string",
353+
/*default=*/"\"\"",
354+
"String description (LLVM format) of the data layout that is "
355+
"expected on the produced module">,
356+
];
357+
}
358+
344359
def ConvertFuncToLLVMPass : Pass<"convert-func-to-llvm", "ModuleOp"> {
345360
let summary = "Convert from the Func dialect to the LLVM dialect";
346361
let description = [{
@@ -357,6 +372,11 @@ def ConvertFuncToLLVMPass : Pass<"convert-func-to-llvm", "ModuleOp"> {
357372
IR dialect operations, the pass will fail. Any LLVM IR operations or types
358373
already present in the IR will be kept as is.
359374

375+
An LLVM datalayout string can be attached as an attribute to the module on
376+
which the pass anchors. Such an attribute is attached by calling the
377+
set-module-datalayout pass. If present, an llvm::DataLayout object is
378+
created from this attribute and used in the conversion to LLVM.
379+
360380
#### Output IR
361381

362382
Functions converted to LLVM IR. Function arguments types are converted
@@ -374,10 +394,6 @@ def ConvertFuncToLLVMPass : Pass<"convert-func-to-llvm", "ModuleOp"> {
374394
Option<"indexBitwidth", "index-bitwidth", "unsigned",
375395
/*default=kDeriveIndexBitwidthFromDataLayout*/"0",
376396
"Bitwidth of the index type, 0 to use size of machine word">,
377-
Option<"dataLayout", "data-layout", "std::string",
378-
/*default=*/"\"\"",
379-
"String description (LLVM format) of the data layout that is "
380-
"expected on the produced module">,
381397
Option<"useOpaquePointers", "use-opaque-pointers", "bool",
382398
/*default=*/"true", "Generate LLVM IR using opaque pointers "
383399
"instead of typed pointers">,

mlir/lib/Conversion/FuncToLLVM/FuncToLLVM.cpp

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,15 @@
4343
#include "llvm/IR/DerivedTypes.h"
4444
#include "llvm/IR/IRBuilder.h"
4545
#include "llvm/IR/Type.h"
46+
#include "llvm/Support/Casting.h"
4647
#include "llvm/Support/CommandLine.h"
4748
#include "llvm/Support/FormatVariadic.h"
4849
#include <algorithm>
4950
#include <functional>
5051

5152
namespace mlir {
5253
#define GEN_PASS_DEF_CONVERTFUNCTOLLVMPASS
54+
#define GEN_PASS_DEF_SETLLVMMODULEDATALAYOUTPASS
5355
#include "mlir/Conversion/Passes.h.inc"
5456
} // namespace mlir
5557

@@ -746,23 +748,29 @@ struct ConvertFuncToLLVMPass
746748

747749
/// Run the dialect converter on the module.
748750
void runOnOperation() override {
751+
ModuleOp m = getOperation();
752+
StringRef dataLayout;
753+
auto dataLayoutAttr = dyn_cast_or_null<StringAttr>(
754+
m->getAttr(LLVM::LLVMDialect::getDataLayoutAttrName()));
755+
if (dataLayoutAttr)
756+
dataLayout = dataLayoutAttr.getValue();
757+
749758
if (failed(LLVM::LLVMDialect::verifyDataLayoutString(
750-
this->dataLayout, [this](const Twine &message) {
759+
dataLayout, [this](const Twine &message) {
751760
getOperation().emitError() << message.str();
752761
}))) {
753762
signalPassFailure();
754763
return;
755764
}
756765

757-
ModuleOp m = getOperation();
758766
const auto &dataLayoutAnalysis = getAnalysis<DataLayoutAnalysis>();
759767

760768
LowerToLLVMOptions options(&getContext(),
761769
dataLayoutAnalysis.getAtOrAbove(m));
762770
options.useBarePtrCallConv = useBarePtrCallConv;
763771
if (indexBitwidth != kDeriveIndexBitwidthFromDataLayout)
764772
options.overrideIndexBitwidth(indexBitwidth);
765-
options.dataLayout = llvm::DataLayout(this->dataLayout);
773+
options.dataLayout = llvm::DataLayout(dataLayout);
766774
options.useOpaquePointers = useOpaquePointers;
767775

768776
LLVMTypeConverter typeConverter(&getContext(), options,
@@ -778,7 +786,24 @@ struct ConvertFuncToLLVMPass
778786
LLVMConversionTarget target(getContext());
779787
if (failed(applyPartialConversion(m, target, std::move(patterns))))
780788
signalPassFailure();
789+
}
790+
};
791+
792+
struct SetLLVMModuleDataLayoutPass
793+
: public impl::SetLLVMModuleDataLayoutPassBase<
794+
SetLLVMModuleDataLayoutPass> {
795+
using Base::Base;
781796

797+
/// Run the dialect converter on the module.
798+
void runOnOperation() override {
799+
if (failed(LLVM::LLVMDialect::verifyDataLayoutString(
800+
this->dataLayout, [this](const Twine &message) {
801+
getOperation().emitError() << message.str();
802+
}))) {
803+
signalPassFailure();
804+
return;
805+
}
806+
ModuleOp m = getOperation();
782807
m->setAttr(LLVM::LLVMDialect::getDataLayoutAttrName(),
783808
StringAttr::get(m.getContext(), this->dataLayout));
784809
}

mlir/test/Conversion/FuncToLLVM/convert-data-layout.mlir

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
// RUN: mlir-opt -convert-func-to-llvm='use-opaque-pointers=1' %s | FileCheck %s
2-
// RUN-32: mlir-opt -convert-func-to-llvm='data-layout=p:32:32:32 use-opaque-pointers=1' %s | FileCheck %s
1+
// RUN: mlir-opt -set-llvm-module-datalayout -convert-func-to-llvm='use-opaque-pointers=1' %s | FileCheck %s
2+
3+
// RUN-32: mlir-opt -set-llvm-module-datalayout='data-layout=p:32:32:32' -convert-func-to-llvm='use-opaque-pointers=1' %s \
4+
// RUN-32: | FileCheck %s
35

46
// CHECK: module attributes {llvm.data_layout = ""}
57
// CHECK-32: module attributes {llvm.data_layout ="p:32:32:32"}

0 commit comments

Comments
 (0)