Skip to content

Commit 72e8b9a

Browse files
authored
[MLIR] Add a BlobAttr interface for attribute to wrap arbitrary content and use it as linkLibs for ModuleToObject (#120116)
This change allows to expose through an interface attributes wrapping content as external resources, and the usage inside the ModuleToObject show how we will be able to provide runtime libraries without relying on the filesystem.
1 parent 41a6e9c commit 72e8b9a

File tree

14 files changed

+213
-57
lines changed

14 files changed

+213
-57
lines changed

mlir/include/mlir/Dialect/GPU/IR/CompilationInterfaces.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class TargetOptions {
5151
/// obtaining the parent symbol table. The default compilation target is
5252
/// `Fatbin`.
5353
TargetOptions(
54-
StringRef toolkitPath = {}, ArrayRef<std::string> linkFiles = {},
54+
StringRef toolkitPath = {}, ArrayRef<Attribute> librariesToLink = {},
5555
StringRef cmdOptions = {}, StringRef elfSection = {},
5656
CompilationTarget compilationTarget = getDefaultCompilationTarget(),
5757
function_ref<SymbolTable *()> getSymbolTableCallback = {},
@@ -66,8 +66,8 @@ class TargetOptions {
6666
/// Returns the toolkit path.
6767
StringRef getToolkitPath() const;
6868

69-
/// Returns the files to link to.
70-
ArrayRef<std::string> getLinkFiles() const;
69+
/// Returns the LLVM libraries to link to.
70+
ArrayRef<Attribute> getLibrariesToLink() const;
7171

7272
/// Returns the command line options.
7373
StringRef getCmdOptions() const;
@@ -113,7 +113,7 @@ class TargetOptions {
113113
/// appropiate value: ie. `TargetOptions(TypeID::get<DerivedClass>())`.
114114
TargetOptions(
115115
TypeID typeID, StringRef toolkitPath = {},
116-
ArrayRef<std::string> linkFiles = {}, StringRef cmdOptions = {},
116+
ArrayRef<Attribute> librariesToLink = {}, StringRef cmdOptions = {},
117117
StringRef elfSection = {},
118118
CompilationTarget compilationTarget = getDefaultCompilationTarget(),
119119
function_ref<SymbolTable *()> getSymbolTableCallback = {},
@@ -126,7 +126,7 @@ class TargetOptions {
126126
std::string toolkitPath;
127127

128128
/// List of files to link with the LLVM module.
129-
SmallVector<std::string> linkFiles;
129+
SmallVector<Attribute> librariesToLink;
130130

131131
/// An optional set of command line options to be used by the compilation
132132
/// process.

mlir/include/mlir/IR/BuiltinAttributeInterfaces.td

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,24 @@ def TypedAttrInterface : AttrInterface<"TypedAttr"> {
3434
>];
3535
}
3636

37+
//===----------------------------------------------------------------------===//
38+
// BlobAttrInterface
39+
//===----------------------------------------------------------------------===//
40+
41+
def BlobAttrInterface : AttrInterface<"BlobAttr"> {
42+
let cppNamespace = "::mlir";
43+
let description = [{
44+
This interface allows an attribute to expose a blob of data without more
45+
information. The data must be stored so that it can be accessed as a
46+
contiguous ArrayRef.
47+
}];
48+
49+
let methods = [InterfaceMethod<
50+
"Get the attribute's data",
51+
"::llvm::ArrayRef<char>", "getData"
52+
>];
53+
}
54+
3755
//===----------------------------------------------------------------------===//
3856
// ElementsAttrInterface
3957
//===----------------------------------------------------------------------===//

mlir/include/mlir/IR/BuiltinAttributes.td

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,8 @@ def Builtin_DenseArrayRawDataParameter : ArrayRefParameter<
153153
}];
154154
}
155155

156-
def Builtin_DenseArray : Builtin_Attr<"DenseArray", "dense_array"> {
156+
def Builtin_DenseArray : Builtin_Attr<"DenseArray", "dense_array",
157+
[BlobAttrInterface]> {
157158
let summary = "A dense array of integer or floating point elements.";
158159
let description = [{
159160
A dense array attribute is an attribute that represents a dense array of
@@ -211,6 +212,10 @@ def Builtin_DenseArray : Builtin_Attr<"DenseArray", "dense_array"> {
211212
int64_t size() const { return getSize(); }
212213
/// Return true if there are no elements in the dense array.
213214
bool empty() const { return !size(); }
215+
/// BlobAttrInterface method.
216+
ArrayRef<char> getData() {
217+
return getRawData();
218+
}
214219
}];
215220
}
216221

@@ -431,7 +436,7 @@ def Builtin_DenseStringElementsAttr : Builtin_Attr<
431436
//===----------------------------------------------------------------------===//
432437

433438
def Builtin_DenseResourceElementsAttr : Builtin_Attr<"DenseResourceElements",
434-
"dense_resource_elements", [ElementsAttrInterface]> {
439+
"dense_resource_elements", [ElementsAttrInterface, BlobAttrInterface]> {
435440
let summary = "An Attribute containing a dense multi-dimensional array "
436441
"backed by a resource";
437442
let description = [{
@@ -485,6 +490,10 @@ def Builtin_DenseResourceElementsAttr : Builtin_Attr<"DenseResourceElements",
485490
"ShapedType":$type, "StringRef":$blobName, "AsmResourceBlob":$blob
486491
)>
487492
];
493+
let extraClassDeclaration = [{
494+
/// BlobAttrInterface method.
495+
ArrayRef<char> getData();
496+
}];
488497

489498
let skipDefaultBuilders = 1;
490499
}

mlir/include/mlir/Target/LLVM/ModuleToObject.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class ModuleToObject {
8383

8484
/// Loads multiple bitcode files.
8585
LogicalResult loadBitcodeFilesFromList(
86-
llvm::LLVMContext &context, ArrayRef<std::string> fileList,
86+
llvm::LLVMContext &context, ArrayRef<Attribute> librariesToLink,
8787
SmallVector<std::unique_ptr<llvm::Module>> &llvmModules,
8888
bool failureOnError = true);
8989

mlir/include/mlir/Target/LLVM/NVVM/Utils.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,15 @@ class SerializeGPUModuleBase : public LLVM::ModuleToObject {
4646
/// Returns the CUDA toolkit path.
4747
StringRef getToolkitPath() const;
4848

49-
/// Returns the bitcode files to be loaded.
50-
ArrayRef<std::string> getFileList() const;
49+
/// Returns the bitcode libraries to be linked into the gpu module after
50+
/// translation to LLVM IR.
51+
ArrayRef<Attribute> getLibrariesToLink() const;
5152

52-
/// Appends `nvvm/libdevice.bc` into `fileList`. Returns failure if the
53+
/// Appends `nvvm/libdevice.bc` into `librariesToLink`. Returns failure if the
5354
/// library couldn't be found.
5455
LogicalResult appendStandardLibs();
5556

56-
/// Loads the bitcode files in `fileList`.
57+
/// Loads the bitcode files in `librariesToLink`.
5758
virtual std::optional<SmallVector<std::unique_ptr<llvm::Module>>>
5859
loadBitcodeFiles(llvm::Module &module) override;
5960

@@ -64,8 +65,10 @@ class SerializeGPUModuleBase : public LLVM::ModuleToObject {
6465
/// CUDA toolkit path.
6566
std::string toolkitPath;
6667

67-
/// List of LLVM bitcode files to link to.
68-
SmallVector<std::string> fileList;
68+
/// List of LLVM bitcode to link into after translation to LLVM IR.
69+
/// The attributes can be StringAttr pointing to a file path, or
70+
/// a Resource blob pointing to the LLVM bitcode in-memory.
71+
SmallVector<Attribute> librariesToLink;
6972
};
7073
} // namespace NVVM
7174
} // namespace mlir

mlir/include/mlir/Target/LLVM/ROCDL/Utils.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "mlir/Dialect/GPU/IR/CompilationInterfaces.h"
1717
#include "mlir/Dialect/GPU/IR/GPUDialect.h"
1818
#include "mlir/Dialect/LLVMIR/ROCDLDialect.h"
19+
#include "mlir/IR/Attributes.h"
1920
#include "mlir/Support/LLVM.h"
2021
#include "mlir/Target/LLVM/ModuleToObject.h"
2122

@@ -61,8 +62,8 @@ class SerializeGPUModuleBase : public LLVM::ModuleToObject {
6162
/// Returns the ROCM toolkit path.
6263
StringRef getToolkitPath() const;
6364

64-
/// Returns the bitcode files to be loaded.
65-
ArrayRef<std::string> getFileList() const;
65+
/// Returns the LLVM bitcode libraries to be linked.
66+
ArrayRef<Attribute> getLibrariesToLink() const;
6667

6768
/// Appends standard ROCm device libraries to `fileList`.
6869
LogicalResult appendStandardLibs(AMDGCNLibraries libs);
@@ -107,7 +108,7 @@ class SerializeGPUModuleBase : public LLVM::ModuleToObject {
107108
std::string toolkitPath;
108109

109110
/// List of LLVM bitcode files to link to.
110-
SmallVector<std::string> fileList;
111+
SmallVector<Attribute> librariesToLink;
111112

112113
/// AMD GCN libraries to use when linking, the default is using none.
113114
AMDGCNLibraries deviceLibs = AMDGCNLibraries::None;

mlir/lib/Dialect/GPU/IR/GPUDialect.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2483,30 +2483,30 @@ KernelMetadataAttr KernelTableAttr::lookup(StringAttr key) const {
24832483
//===----------------------------------------------------------------------===//
24842484

24852485
TargetOptions::TargetOptions(
2486-
StringRef toolkitPath, ArrayRef<std::string> linkFiles,
2486+
StringRef toolkitPath, ArrayRef<Attribute> librariesToLink,
24872487
StringRef cmdOptions, StringRef elfSection,
24882488
CompilationTarget compilationTarget,
24892489
function_ref<SymbolTable *()> getSymbolTableCallback,
24902490
function_ref<void(llvm::Module &)> initialLlvmIRCallback,
24912491
function_ref<void(llvm::Module &)> linkedLlvmIRCallback,
24922492
function_ref<void(llvm::Module &)> optimizedLlvmIRCallback,
24932493
function_ref<void(StringRef)> isaCallback)
2494-
: TargetOptions(TypeID::get<TargetOptions>(), toolkitPath, linkFiles,
2494+
: TargetOptions(TypeID::get<TargetOptions>(), toolkitPath, librariesToLink,
24952495
cmdOptions, elfSection, compilationTarget,
24962496
getSymbolTableCallback, initialLlvmIRCallback,
24972497
linkedLlvmIRCallback, optimizedLlvmIRCallback,
24982498
isaCallback) {}
24992499

25002500
TargetOptions::TargetOptions(
2501-
TypeID typeID, StringRef toolkitPath, ArrayRef<std::string> linkFiles,
2501+
TypeID typeID, StringRef toolkitPath, ArrayRef<Attribute> librariesToLink,
25022502
StringRef cmdOptions, StringRef elfSection,
25032503
CompilationTarget compilationTarget,
25042504
function_ref<SymbolTable *()> getSymbolTableCallback,
25052505
function_ref<void(llvm::Module &)> initialLlvmIRCallback,
25062506
function_ref<void(llvm::Module &)> linkedLlvmIRCallback,
25072507
function_ref<void(llvm::Module &)> optimizedLlvmIRCallback,
25082508
function_ref<void(StringRef)> isaCallback)
2509-
: toolkitPath(toolkitPath.str()), linkFiles(linkFiles),
2509+
: toolkitPath(toolkitPath.str()), librariesToLink(librariesToLink),
25102510
cmdOptions(cmdOptions.str()), elfSection(elfSection.str()),
25112511
compilationTarget(compilationTarget),
25122512
getSymbolTableCallback(getSymbolTableCallback),
@@ -2519,7 +2519,9 @@ TypeID TargetOptions::getTypeID() const { return typeID; }
25192519

25202520
StringRef TargetOptions::getToolkitPath() const { return toolkitPath; }
25212521

2522-
ArrayRef<std::string> TargetOptions::getLinkFiles() const { return linkFiles; }
2522+
ArrayRef<Attribute> TargetOptions::getLibrariesToLink() const {
2523+
return librariesToLink;
2524+
}
25232525

25242526
StringRef TargetOptions::getCmdOptions() const { return cmdOptions; }
25252527

mlir/lib/Dialect/GPU/Transforms/ModuleToBinary.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,11 @@ void GpuModuleToBinaryPass::runOnOperation() {
6868
}
6969
return &parentTable.value();
7070
};
71-
72-
TargetOptions targetOptions(toolkitPath, linkFiles, cmdOptions, elfSection,
73-
*targetFormat, lazyTableBuilder);
71+
SmallVector<Attribute> librariesToLink;
72+
for (const std::string &path : linkFiles)
73+
librariesToLink.push_back(StringAttr::get(&getContext(), path));
74+
TargetOptions targetOptions(toolkitPath, librariesToLink, cmdOptions,
75+
elfSection, *targetFormat, lazyTableBuilder);
7476
if (failed(transformGpuModulesToBinaries(
7577
getOperation(), OffloadingLLVMTranslationAttrInterface(nullptr),
7678
targetOptions)))

mlir/lib/IR/BuiltinAttributes.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,6 +1544,12 @@ DenseResourceElementsAttr DenseResourceElementsAttr::get(ShapedType type,
15441544
return get(type, manager.insert(blobName, std::move(blob)));
15451545
}
15461546

1547+
ArrayRef<char> DenseResourceElementsAttr::getData() {
1548+
if (AsmResourceBlob *blob = this->getRawHandle().getBlob())
1549+
return blob->getDataAs<char>();
1550+
return {};
1551+
}
1552+
15471553
//===----------------------------------------------------------------------===//
15481554
// DenseResourceElementsAttrBase
15491555

mlir/lib/Target/LLVM/ModuleToObject.cpp

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#include "mlir/Target/LLVM/ModuleToObject.h"
1515

1616
#include "mlir/ExecutionEngine/OptUtils.h"
17+
#include "mlir/IR/BuiltinAttributeInterfaces.h"
18+
#include "mlir/IR/BuiltinAttributes.h"
1719
#include "mlir/IR/BuiltinOps.h"
1820
#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
1921
#include "mlir/Target/LLVMIR/Export.h"
@@ -25,6 +27,7 @@
2527
#include "llvm/Linker/Linker.h"
2628
#include "llvm/MC/TargetRegistry.h"
2729
#include "llvm/Support/FileSystem.h"
30+
#include "llvm/Support/MemoryBuffer.h"
2831
#include "llvm/Support/Path.h"
2932
#include "llvm/Support/SourceMgr.h"
3033
#include "llvm/Support/raw_ostream.h"
@@ -89,22 +92,53 @@ ModuleToObject::loadBitcodeFile(llvm::LLVMContext &context, StringRef path) {
8992
}
9093

9194
LogicalResult ModuleToObject::loadBitcodeFilesFromList(
92-
llvm::LLVMContext &context, ArrayRef<std::string> fileList,
95+
llvm::LLVMContext &context, ArrayRef<Attribute> librariesToLink,
9396
SmallVector<std::unique_ptr<llvm::Module>> &llvmModules,
9497
bool failureOnError) {
95-
for (const std::string &str : fileList) {
96-
// Test if the path exists, if it doesn't abort.
97-
StringRef pathRef = StringRef(str.data(), str.size());
98-
if (!llvm::sys::fs::is_regular_file(pathRef)) {
98+
for (Attribute linkLib : librariesToLink) {
99+
// Attributes in this list can be either list of file paths using
100+
// StringAttr, or a resource attribute pointing to the LLVM bitcode in
101+
// memory.
102+
if (auto filePath = dyn_cast<StringAttr>(linkLib)) {
103+
// Test if the path exists, if it doesn't abort.
104+
if (!llvm::sys::fs::is_regular_file(filePath.strref())) {
105+
getOperation().emitError()
106+
<< "File path: " << filePath << " does not exist or is not a file.";
107+
return failure();
108+
}
109+
// Load the file or abort on error.
110+
if (auto bcFile = loadBitcodeFile(context, filePath))
111+
llvmModules.push_back(std::move(bcFile));
112+
else if (failureOnError)
113+
return failure();
114+
continue;
115+
}
116+
if (auto blobAttr = dyn_cast<BlobAttr>(linkLib)) {
117+
// Load the file or abort on error.
118+
llvm::SMDiagnostic error;
119+
ArrayRef<char> data = blobAttr.getData();
120+
std::unique_ptr<llvm::MemoryBuffer> buffer =
121+
llvm::MemoryBuffer::getMemBuffer(StringRef(data.data(), data.size()),
122+
"blobLinkedLib",
123+
/*RequiresNullTerminator=*/false);
124+
std::unique_ptr<llvm::Module> mod =
125+
getLazyIRModule(std::move(buffer), error, context);
126+
if (mod) {
127+
if (failed(handleBitcodeFile(*mod)))
128+
return failure();
129+
llvmModules.push_back(std::move(mod));
130+
} else if (failureOnError) {
131+
getOperation().emitError()
132+
<< "Couldn't load LLVM library for linking: " << error.getMessage();
133+
return failure();
134+
}
135+
continue;
136+
}
137+
if (failureOnError) {
99138
getOperation().emitError()
100-
<< "File path: " << pathRef << " does not exist or is not a file.\n";
139+
<< "Unknown attribute describing LLVM library to load: " << linkLib;
101140
return failure();
102141
}
103-
// Load the file or abort on error.
104-
if (auto bcFile = loadBitcodeFile(context, pathRef))
105-
llvmModules.push_back(std::move(bcFile));
106-
else if (failureOnError)
107-
return failure();
108142
}
109143
return success();
110144
}

mlir/lib/Target/LLVM/NVVM/Target.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -93,17 +93,15 @@ SerializeGPUModuleBase::SerializeGPUModuleBase(
9393
targetOptions.getOptimizedLlvmIRCallback(),
9494
targetOptions.getISACallback()),
9595
target(target), toolkitPath(targetOptions.getToolkitPath()),
96-
fileList(targetOptions.getLinkFiles()) {
96+
librariesToLink(targetOptions.getLibrariesToLink()) {
9797

9898
// If `targetOptions` have an empty toolkitPath use `getCUDAToolkitPath`
9999
if (toolkitPath.empty())
100100
toolkitPath = getCUDAToolkitPath();
101101

102102
// Append the files in the target attribute.
103-
if (ArrayAttr files = target.getLink())
104-
for (Attribute attr : files.getValue())
105-
if (auto file = dyn_cast<StringAttr>(attr))
106-
fileList.push_back(file.str());
103+
if (target.getLink())
104+
librariesToLink.append(target.getLink().begin(), target.getLink().end());
107105

108106
// Append libdevice to the files to be loaded.
109107
(void)appendStandardLibs();
@@ -126,8 +124,8 @@ NVVMTargetAttr SerializeGPUModuleBase::getTarget() const { return target; }
126124

127125
StringRef SerializeGPUModuleBase::getToolkitPath() const { return toolkitPath; }
128126

129-
ArrayRef<std::string> SerializeGPUModuleBase::getFileList() const {
130-
return fileList;
127+
ArrayRef<Attribute> SerializeGPUModuleBase::getLibrariesToLink() const {
128+
return librariesToLink;
131129
}
132130

133131
// Try to append `libdevice` from a CUDA toolkit installation.
@@ -149,16 +147,16 @@ LogicalResult SerializeGPUModuleBase::appendStandardLibs() {
149147
<< " does not exist or is not a file.\n";
150148
return failure();
151149
}
152-
fileList.push_back(pathRef.str());
150+
librariesToLink.push_back(StringAttr::get(target.getContext(), pathRef));
153151
}
154152
return success();
155153
}
156154

157155
std::optional<SmallVector<std::unique_ptr<llvm::Module>>>
158156
SerializeGPUModuleBase::loadBitcodeFiles(llvm::Module &module) {
159157
SmallVector<std::unique_ptr<llvm::Module>> bcFiles;
160-
if (failed(loadBitcodeFilesFromList(module.getContext(), fileList, bcFiles,
161-
true)))
158+
if (failed(loadBitcodeFilesFromList(module.getContext(), librariesToLink,
159+
bcFiles, true)))
162160
return std::nullopt;
163161
return std::move(bcFiles);
164162
}

0 commit comments

Comments
 (0)