Skip to content

[mlir][gpu] Adding ELF section option to the gpu-module-to-binary pass #119440

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Dec 16, 2024

Conversation

Renaud-K
Copy link
Contributor

@Renaud-K Renaud-K commented Dec 10, 2024

This is a follow-up of #117246.

I thought then it would be easy to edit a DictionaryAttr but it turns out that these attributes are immutable and need to be passed during the construction of the gpu.binary Op.

The first commit was using the NVVMTargetAttr to pass the information. After feedback from @fabianmcg, this PR now passes the information through a new option of the gpu-module-to-binary pass.

Please add reviewers, as you see fit.

@llvmbot
Copy link
Member

llvmbot commented Dec 10, 2024

@llvm/pr-subscribers-mlir-llvm

Author: Renaud Kauffmann (Renaud-K)

Changes

This is a follow-up of #117246.

I thought then it would be easy to edit a DictionaryAttr but it turns out that these attributes are immutable and need to be passed during the construction of the gpu.binary Op. This requires the section to be part of the NVVMTargetAttr and to be an option to the GpuNVVMAttachTarget pass.


Full diff: https://github.com/llvm/llvm-project/pull/119440.diff

6 Files Affected:

  • (modified) mlir/include/mlir/Dialect/GPU/Transforms/Passes.td (+3)
  • (modified) mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td (+4-2)
  • (modified) mlir/lib/Dialect/GPU/Transforms/NVVMAttachTarget.cpp (+3-1)
  • (modified) mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp (+1-1)
  • (modified) mlir/lib/Target/LLVM/NVVM/Target.cpp (+11-2)
  • (modified) mlir/test/Dialect/LLVMIR/attach-targets.mlir (+3)
diff --git a/mlir/include/mlir/Dialect/GPU/Transforms/Passes.td b/mlir/include/mlir/Dialect/GPU/Transforms/Passes.td
index 4a9ddafdd177d2..784721d19d0ccd 100644
--- a/mlir/include/mlir/Dialect/GPU/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/GPU/Transforms/Passes.td
@@ -139,6 +139,9 @@ def GpuNVVMAttachTarget: Pass<"nvvm-attach-target", ""> {
     Option<"ftzFlag", "ftz", "bool",
            /*default=*/"false",
            "Enable flush to zero for denormals.">,
+    Option<"elfSection", "section", "std::string",
+           /*default=*/"\"\"",
+           "ELF section where the module needs to be created.">,
     ListOption<"linkLibs", "l", "std::string",
            "Extra bitcode libraries paths to link to.">,
   ];
diff --git a/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td
index 296a3c305e5bf4..03c03d5f66b9af 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td
@@ -2266,20 +2266,22 @@ def NVVM_TargettAttr : NVVM_Attr<"NVVMTarget", "target"> {
     StringRefParameter<"Target triple.", "\"nvptx64-nvidia-cuda\"">:$triple,
     StringRefParameter<"Target chip.", "\"sm_50\"">:$chip,
     StringRefParameter<"Target chip features.", "\"+ptx60\"">:$features,
+    OptionalParameter<"StringAttr", "ELF section.">:$section,
     OptionalParameter<"DictionaryAttr", "Target specific flags.">:$flags,
     OptionalParameter<"ArrayAttr", "Files to link to the LLVM module.">:$link
   );
   let assemblyFormat = [{
-    (`<` struct($O, $triple, $chip, $features, $flags, $link)^ `>`)?
+    (`<` struct($O, $triple, $chip, $features, $section, $flags, $link)^ `>`)?
   }];
   let builders = [
     AttrBuilder<(ins CArg<"int", "2">:$optLevel,
                      CArg<"StringRef", "\"nvptx64-nvidia-cuda\"">:$triple,
                      CArg<"StringRef", "\"sm_50\"">:$chip,
                      CArg<"StringRef", "\"+ptx60\"">:$features,
+                     CArg<"StringAttr", "nullptr">:$section,
                      CArg<"DictionaryAttr", "nullptr">:$targetFlags,
                      CArg<"ArrayAttr", "nullptr">:$linkFiles), [{
-      return Base::get($_ctxt, optLevel, triple, chip, features, targetFlags, linkFiles);
+      return Base::get($_ctxt, optLevel, triple, chip, features, section, targetFlags, linkFiles);
     }]>
   ];
   let skipDefaultBuilders = 1;
diff --git a/mlir/lib/Dialect/GPU/Transforms/NVVMAttachTarget.cpp b/mlir/lib/Dialect/GPU/Transforms/NVVMAttachTarget.cpp
index dd705cd3383121..5628361c6a843c 100644
--- a/mlir/lib/Dialect/GPU/Transforms/NVVMAttachTarget.cpp
+++ b/mlir/lib/Dialect/GPU/Transforms/NVVMAttachTarget.cpp
@@ -63,7 +63,9 @@ void NVVMAttachTarget::runOnOperation() {
   ArrayRef<std::string> libs(linkLibs);
   SmallVector<StringRef> filesToLink(libs);
   auto target = builder.getAttr<NVVMTargetAttr>(
-      optLevel, triple, chip, features, getFlags(builder),
+      optLevel, triple, chip, features,
+      elfSection.empty() ? nullptr : builder.getStringAttr(elfSection),
+      getFlags(builder),
       filesToLink.empty() ? nullptr : builder.getStrArrayAttr(filesToLink));
   llvm::Regex matcher(moduleMatcher);
   for (Region &region : getOperation()->getRegions())
diff --git a/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
index ca04af0b060b4f..696cab52d41900 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
@@ -1185,7 +1185,7 @@ LogicalResult NVVMDialect::verifyRegionArgAttribute(Operation *op,
 LogicalResult
 NVVMTargetAttr::verify(function_ref<InFlightDiagnostic()> emitError,
                        int optLevel, StringRef triple, StringRef chip,
-                       StringRef features, DictionaryAttr flags,
+                       StringRef features, StringAttr elfSection, DictionaryAttr flags,
                        ArrayAttr files) {
   if (optLevel < 0 || optLevel > 3) {
     emitError() << "The optimization level must be a number between 0 and 3.";
diff --git a/mlir/lib/Target/LLVM/NVVM/Target.cpp b/mlir/lib/Target/LLVM/NVVM/Target.cpp
index 3c92359915ded4..82ead374420d9e 100644
--- a/mlir/lib/Target/LLVM/NVVM/Target.cpp
+++ b/mlir/lib/Target/LLVM/NVVM/Target.cpp
@@ -664,9 +664,18 @@ NVVMTargetAttrImpl::createObject(Attribute attribute, Operation *module,
   gpu::CompilationTarget format = options.getCompilationTarget();
   DictionaryAttr objectProps;
   Builder builder(attribute.getContext());
+  SmallVector<NamedAttribute, 2> properties;
   if (format == gpu::CompilationTarget::Assembly)
-    objectProps = builder.getDictionaryAttr(
-        {builder.getNamedAttr("O", builder.getI32IntegerAttr(target.getO()))});
+    properties.push_back(
+        builder.getNamedAttr("O", builder.getI32IntegerAttr(target.getO())));
+
+  if (StringAttr section = target.getSection())   
+    properties.push_back(
+        builder.getNamedAttr("section", section));
+  
+  if (!properties.empty())
+    objectProps = builder.getDictionaryAttr(properties);
+
   return builder.getAttr<gpu::ObjectAttr>(
       attribute, format,
       builder.getStringAttr(StringRef(object.data(), object.size())),
diff --git a/mlir/test/Dialect/LLVMIR/attach-targets.mlir b/mlir/test/Dialect/LLVMIR/attach-targets.mlir
index 83733db400798e..832e0443e720f7 100644
--- a/mlir/test/Dialect/LLVMIR/attach-targets.mlir
+++ b/mlir/test/Dialect/LLVMIR/attach-targets.mlir
@@ -1,13 +1,16 @@
 // RUN: mlir-opt %s --nvvm-attach-target='module=nvvm.* O=3 chip=sm_90' --rocdl-attach-target='module=rocdl.* O=3 chip=gfx90a' | FileCheck %s
 // RUN: mlir-opt %s --nvvm-attach-target='module=options.* O=1 chip=sm_70 fast=true ftz=true' --rocdl-attach-target='module=options.* l=file1.bc,file2.bc wave64=false finite-only=true' | FileCheck %s --check-prefix=CHECK_OPTS
+// RUN: mlir-opt %s --nvvm-attach-target='module=nvvm.* section=__fatbin' | FileCheck %s --check-prefix=CHECK_SECTION
 
 module attributes {gpu.container_module} {
 // Verify the target is appended.
 // CHECK: @nvvm_module_1 [#nvvm.target<O = 3, chip = "sm_90">] {
+// CHECK_SECTION: @nvvm_module_1 [#nvvm.target<section = "__fatbin">] 
 gpu.module @nvvm_module_1 {
 }
 // Verify the target is appended.
 // CHECK: @nvvm_module_2 [#nvvm.target<chip = "sm_60">, #nvvm.target<O = 3, chip = "sm_90">] {
+// CHECK_SECTION: gpu.module @nvvm_module_2 [#nvvm.target<chip = "sm_60">, #nvvm.target<section = "__fatbin">] 
 gpu.module @nvvm_module_2 [#nvvm.target<chip = "sm_60">] {
 }
 // Verify the target is not added multiple times.

@llvmbot
Copy link
Member

llvmbot commented Dec 10, 2024

@llvm/pr-subscribers-mlir

Author: Renaud Kauffmann (Renaud-K)

Changes

This is a follow-up of #117246.

I thought then it would be easy to edit a DictionaryAttr but it turns out that these attributes are immutable and need to be passed during the construction of the gpu.binary Op. This requires the section to be part of the NVVMTargetAttr and to be an option to the GpuNVVMAttachTarget pass.


Full diff: https://github.com/llvm/llvm-project/pull/119440.diff

6 Files Affected:

  • (modified) mlir/include/mlir/Dialect/GPU/Transforms/Passes.td (+3)
  • (modified) mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td (+4-2)
  • (modified) mlir/lib/Dialect/GPU/Transforms/NVVMAttachTarget.cpp (+3-1)
  • (modified) mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp (+1-1)
  • (modified) mlir/lib/Target/LLVM/NVVM/Target.cpp (+11-2)
  • (modified) mlir/test/Dialect/LLVMIR/attach-targets.mlir (+3)
diff --git a/mlir/include/mlir/Dialect/GPU/Transforms/Passes.td b/mlir/include/mlir/Dialect/GPU/Transforms/Passes.td
index 4a9ddafdd177d2..784721d19d0ccd 100644
--- a/mlir/include/mlir/Dialect/GPU/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/GPU/Transforms/Passes.td
@@ -139,6 +139,9 @@ def GpuNVVMAttachTarget: Pass<"nvvm-attach-target", ""> {
     Option<"ftzFlag", "ftz", "bool",
            /*default=*/"false",
            "Enable flush to zero for denormals.">,
+    Option<"elfSection", "section", "std::string",
+           /*default=*/"\"\"",
+           "ELF section where the module needs to be created.">,
     ListOption<"linkLibs", "l", "std::string",
            "Extra bitcode libraries paths to link to.">,
   ];
diff --git a/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td
index 296a3c305e5bf4..03c03d5f66b9af 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td
@@ -2266,20 +2266,22 @@ def NVVM_TargettAttr : NVVM_Attr<"NVVMTarget", "target"> {
     StringRefParameter<"Target triple.", "\"nvptx64-nvidia-cuda\"">:$triple,
     StringRefParameter<"Target chip.", "\"sm_50\"">:$chip,
     StringRefParameter<"Target chip features.", "\"+ptx60\"">:$features,
+    OptionalParameter<"StringAttr", "ELF section.">:$section,
     OptionalParameter<"DictionaryAttr", "Target specific flags.">:$flags,
     OptionalParameter<"ArrayAttr", "Files to link to the LLVM module.">:$link
   );
   let assemblyFormat = [{
-    (`<` struct($O, $triple, $chip, $features, $flags, $link)^ `>`)?
+    (`<` struct($O, $triple, $chip, $features, $section, $flags, $link)^ `>`)?
   }];
   let builders = [
     AttrBuilder<(ins CArg<"int", "2">:$optLevel,
                      CArg<"StringRef", "\"nvptx64-nvidia-cuda\"">:$triple,
                      CArg<"StringRef", "\"sm_50\"">:$chip,
                      CArg<"StringRef", "\"+ptx60\"">:$features,
+                     CArg<"StringAttr", "nullptr">:$section,
                      CArg<"DictionaryAttr", "nullptr">:$targetFlags,
                      CArg<"ArrayAttr", "nullptr">:$linkFiles), [{
-      return Base::get($_ctxt, optLevel, triple, chip, features, targetFlags, linkFiles);
+      return Base::get($_ctxt, optLevel, triple, chip, features, section, targetFlags, linkFiles);
     }]>
   ];
   let skipDefaultBuilders = 1;
diff --git a/mlir/lib/Dialect/GPU/Transforms/NVVMAttachTarget.cpp b/mlir/lib/Dialect/GPU/Transforms/NVVMAttachTarget.cpp
index dd705cd3383121..5628361c6a843c 100644
--- a/mlir/lib/Dialect/GPU/Transforms/NVVMAttachTarget.cpp
+++ b/mlir/lib/Dialect/GPU/Transforms/NVVMAttachTarget.cpp
@@ -63,7 +63,9 @@ void NVVMAttachTarget::runOnOperation() {
   ArrayRef<std::string> libs(linkLibs);
   SmallVector<StringRef> filesToLink(libs);
   auto target = builder.getAttr<NVVMTargetAttr>(
-      optLevel, triple, chip, features, getFlags(builder),
+      optLevel, triple, chip, features,
+      elfSection.empty() ? nullptr : builder.getStringAttr(elfSection),
+      getFlags(builder),
       filesToLink.empty() ? nullptr : builder.getStrArrayAttr(filesToLink));
   llvm::Regex matcher(moduleMatcher);
   for (Region &region : getOperation()->getRegions())
diff --git a/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
index ca04af0b060b4f..696cab52d41900 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
@@ -1185,7 +1185,7 @@ LogicalResult NVVMDialect::verifyRegionArgAttribute(Operation *op,
 LogicalResult
 NVVMTargetAttr::verify(function_ref<InFlightDiagnostic()> emitError,
                        int optLevel, StringRef triple, StringRef chip,
-                       StringRef features, DictionaryAttr flags,
+                       StringRef features, StringAttr elfSection, DictionaryAttr flags,
                        ArrayAttr files) {
   if (optLevel < 0 || optLevel > 3) {
     emitError() << "The optimization level must be a number between 0 and 3.";
diff --git a/mlir/lib/Target/LLVM/NVVM/Target.cpp b/mlir/lib/Target/LLVM/NVVM/Target.cpp
index 3c92359915ded4..82ead374420d9e 100644
--- a/mlir/lib/Target/LLVM/NVVM/Target.cpp
+++ b/mlir/lib/Target/LLVM/NVVM/Target.cpp
@@ -664,9 +664,18 @@ NVVMTargetAttrImpl::createObject(Attribute attribute, Operation *module,
   gpu::CompilationTarget format = options.getCompilationTarget();
   DictionaryAttr objectProps;
   Builder builder(attribute.getContext());
+  SmallVector<NamedAttribute, 2> properties;
   if (format == gpu::CompilationTarget::Assembly)
-    objectProps = builder.getDictionaryAttr(
-        {builder.getNamedAttr("O", builder.getI32IntegerAttr(target.getO()))});
+    properties.push_back(
+        builder.getNamedAttr("O", builder.getI32IntegerAttr(target.getO())));
+
+  if (StringAttr section = target.getSection())   
+    properties.push_back(
+        builder.getNamedAttr("section", section));
+  
+  if (!properties.empty())
+    objectProps = builder.getDictionaryAttr(properties);
+
   return builder.getAttr<gpu::ObjectAttr>(
       attribute, format,
       builder.getStringAttr(StringRef(object.data(), object.size())),
diff --git a/mlir/test/Dialect/LLVMIR/attach-targets.mlir b/mlir/test/Dialect/LLVMIR/attach-targets.mlir
index 83733db400798e..832e0443e720f7 100644
--- a/mlir/test/Dialect/LLVMIR/attach-targets.mlir
+++ b/mlir/test/Dialect/LLVMIR/attach-targets.mlir
@@ -1,13 +1,16 @@
 // RUN: mlir-opt %s --nvvm-attach-target='module=nvvm.* O=3 chip=sm_90' --rocdl-attach-target='module=rocdl.* O=3 chip=gfx90a' | FileCheck %s
 // RUN: mlir-opt %s --nvvm-attach-target='module=options.* O=1 chip=sm_70 fast=true ftz=true' --rocdl-attach-target='module=options.* l=file1.bc,file2.bc wave64=false finite-only=true' | FileCheck %s --check-prefix=CHECK_OPTS
+// RUN: mlir-opt %s --nvvm-attach-target='module=nvvm.* section=__fatbin' | FileCheck %s --check-prefix=CHECK_SECTION
 
 module attributes {gpu.container_module} {
 // Verify the target is appended.
 // CHECK: @nvvm_module_1 [#nvvm.target<O = 3, chip = "sm_90">] {
+// CHECK_SECTION: @nvvm_module_1 [#nvvm.target<section = "__fatbin">] 
 gpu.module @nvvm_module_1 {
 }
 // Verify the target is appended.
 // CHECK: @nvvm_module_2 [#nvvm.target<chip = "sm_60">, #nvvm.target<O = 3, chip = "sm_90">] {
+// CHECK_SECTION: gpu.module @nvvm_module_2 [#nvvm.target<chip = "sm_60">, #nvvm.target<section = "__fatbin">] 
 gpu.module @nvvm_module_2 [#nvvm.target<chip = "sm_60">] {
 }
 // Verify the target is not added multiple times.

@llvmbot
Copy link
Member

llvmbot commented Dec 10, 2024

@llvm/pr-subscribers-mlir-gpu

Author: Renaud Kauffmann (Renaud-K)

Changes

This is a follow-up of #117246.

I thought then it would be easy to edit a DictionaryAttr but it turns out that these attributes are immutable and need to be passed during the construction of the gpu.binary Op. This requires the section to be part of the NVVMTargetAttr and to be an option to the GpuNVVMAttachTarget pass.


Full diff: https://github.com/llvm/llvm-project/pull/119440.diff

6 Files Affected:

  • (modified) mlir/include/mlir/Dialect/GPU/Transforms/Passes.td (+3)
  • (modified) mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td (+4-2)
  • (modified) mlir/lib/Dialect/GPU/Transforms/NVVMAttachTarget.cpp (+3-1)
  • (modified) mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp (+1-1)
  • (modified) mlir/lib/Target/LLVM/NVVM/Target.cpp (+11-2)
  • (modified) mlir/test/Dialect/LLVMIR/attach-targets.mlir (+3)
diff --git a/mlir/include/mlir/Dialect/GPU/Transforms/Passes.td b/mlir/include/mlir/Dialect/GPU/Transforms/Passes.td
index 4a9ddafdd177d2..784721d19d0ccd 100644
--- a/mlir/include/mlir/Dialect/GPU/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/GPU/Transforms/Passes.td
@@ -139,6 +139,9 @@ def GpuNVVMAttachTarget: Pass<"nvvm-attach-target", ""> {
     Option<"ftzFlag", "ftz", "bool",
            /*default=*/"false",
            "Enable flush to zero for denormals.">,
+    Option<"elfSection", "section", "std::string",
+           /*default=*/"\"\"",
+           "ELF section where the module needs to be created.">,
     ListOption<"linkLibs", "l", "std::string",
            "Extra bitcode libraries paths to link to.">,
   ];
diff --git a/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td
index 296a3c305e5bf4..03c03d5f66b9af 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td
@@ -2266,20 +2266,22 @@ def NVVM_TargettAttr : NVVM_Attr<"NVVMTarget", "target"> {
     StringRefParameter<"Target triple.", "\"nvptx64-nvidia-cuda\"">:$triple,
     StringRefParameter<"Target chip.", "\"sm_50\"">:$chip,
     StringRefParameter<"Target chip features.", "\"+ptx60\"">:$features,
+    OptionalParameter<"StringAttr", "ELF section.">:$section,
     OptionalParameter<"DictionaryAttr", "Target specific flags.">:$flags,
     OptionalParameter<"ArrayAttr", "Files to link to the LLVM module.">:$link
   );
   let assemblyFormat = [{
-    (`<` struct($O, $triple, $chip, $features, $flags, $link)^ `>`)?
+    (`<` struct($O, $triple, $chip, $features, $section, $flags, $link)^ `>`)?
   }];
   let builders = [
     AttrBuilder<(ins CArg<"int", "2">:$optLevel,
                      CArg<"StringRef", "\"nvptx64-nvidia-cuda\"">:$triple,
                      CArg<"StringRef", "\"sm_50\"">:$chip,
                      CArg<"StringRef", "\"+ptx60\"">:$features,
+                     CArg<"StringAttr", "nullptr">:$section,
                      CArg<"DictionaryAttr", "nullptr">:$targetFlags,
                      CArg<"ArrayAttr", "nullptr">:$linkFiles), [{
-      return Base::get($_ctxt, optLevel, triple, chip, features, targetFlags, linkFiles);
+      return Base::get($_ctxt, optLevel, triple, chip, features, section, targetFlags, linkFiles);
     }]>
   ];
   let skipDefaultBuilders = 1;
diff --git a/mlir/lib/Dialect/GPU/Transforms/NVVMAttachTarget.cpp b/mlir/lib/Dialect/GPU/Transforms/NVVMAttachTarget.cpp
index dd705cd3383121..5628361c6a843c 100644
--- a/mlir/lib/Dialect/GPU/Transforms/NVVMAttachTarget.cpp
+++ b/mlir/lib/Dialect/GPU/Transforms/NVVMAttachTarget.cpp
@@ -63,7 +63,9 @@ void NVVMAttachTarget::runOnOperation() {
   ArrayRef<std::string> libs(linkLibs);
   SmallVector<StringRef> filesToLink(libs);
   auto target = builder.getAttr<NVVMTargetAttr>(
-      optLevel, triple, chip, features, getFlags(builder),
+      optLevel, triple, chip, features,
+      elfSection.empty() ? nullptr : builder.getStringAttr(elfSection),
+      getFlags(builder),
       filesToLink.empty() ? nullptr : builder.getStrArrayAttr(filesToLink));
   llvm::Regex matcher(moduleMatcher);
   for (Region &region : getOperation()->getRegions())
diff --git a/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
index ca04af0b060b4f..696cab52d41900 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
@@ -1185,7 +1185,7 @@ LogicalResult NVVMDialect::verifyRegionArgAttribute(Operation *op,
 LogicalResult
 NVVMTargetAttr::verify(function_ref<InFlightDiagnostic()> emitError,
                        int optLevel, StringRef triple, StringRef chip,
-                       StringRef features, DictionaryAttr flags,
+                       StringRef features, StringAttr elfSection, DictionaryAttr flags,
                        ArrayAttr files) {
   if (optLevel < 0 || optLevel > 3) {
     emitError() << "The optimization level must be a number between 0 and 3.";
diff --git a/mlir/lib/Target/LLVM/NVVM/Target.cpp b/mlir/lib/Target/LLVM/NVVM/Target.cpp
index 3c92359915ded4..82ead374420d9e 100644
--- a/mlir/lib/Target/LLVM/NVVM/Target.cpp
+++ b/mlir/lib/Target/LLVM/NVVM/Target.cpp
@@ -664,9 +664,18 @@ NVVMTargetAttrImpl::createObject(Attribute attribute, Operation *module,
   gpu::CompilationTarget format = options.getCompilationTarget();
   DictionaryAttr objectProps;
   Builder builder(attribute.getContext());
+  SmallVector<NamedAttribute, 2> properties;
   if (format == gpu::CompilationTarget::Assembly)
-    objectProps = builder.getDictionaryAttr(
-        {builder.getNamedAttr("O", builder.getI32IntegerAttr(target.getO()))});
+    properties.push_back(
+        builder.getNamedAttr("O", builder.getI32IntegerAttr(target.getO())));
+
+  if (StringAttr section = target.getSection())   
+    properties.push_back(
+        builder.getNamedAttr("section", section));
+  
+  if (!properties.empty())
+    objectProps = builder.getDictionaryAttr(properties);
+
   return builder.getAttr<gpu::ObjectAttr>(
       attribute, format,
       builder.getStringAttr(StringRef(object.data(), object.size())),
diff --git a/mlir/test/Dialect/LLVMIR/attach-targets.mlir b/mlir/test/Dialect/LLVMIR/attach-targets.mlir
index 83733db400798e..832e0443e720f7 100644
--- a/mlir/test/Dialect/LLVMIR/attach-targets.mlir
+++ b/mlir/test/Dialect/LLVMIR/attach-targets.mlir
@@ -1,13 +1,16 @@
 // RUN: mlir-opt %s --nvvm-attach-target='module=nvvm.* O=3 chip=sm_90' --rocdl-attach-target='module=rocdl.* O=3 chip=gfx90a' | FileCheck %s
 // RUN: mlir-opt %s --nvvm-attach-target='module=options.* O=1 chip=sm_70 fast=true ftz=true' --rocdl-attach-target='module=options.* l=file1.bc,file2.bc wave64=false finite-only=true' | FileCheck %s --check-prefix=CHECK_OPTS
+// RUN: mlir-opt %s --nvvm-attach-target='module=nvvm.* section=__fatbin' | FileCheck %s --check-prefix=CHECK_SECTION
 
 module attributes {gpu.container_module} {
 // Verify the target is appended.
 // CHECK: @nvvm_module_1 [#nvvm.target<O = 3, chip = "sm_90">] {
+// CHECK_SECTION: @nvvm_module_1 [#nvvm.target<section = "__fatbin">] 
 gpu.module @nvvm_module_1 {
 }
 // Verify the target is appended.
 // CHECK: @nvvm_module_2 [#nvvm.target<chip = "sm_60">, #nvvm.target<O = 3, chip = "sm_90">] {
+// CHECK_SECTION: gpu.module @nvvm_module_2 [#nvvm.target<chip = "sm_60">, #nvvm.target<section = "__fatbin">] 
 gpu.module @nvvm_module_2 [#nvvm.target<chip = "sm_60">] {
 }
 // Verify the target is not added multiple times.

@Renaud-K Renaud-K changed the title Adding the ELF section to the NVVMTargetAttr, to propagate to the gpu.binary Op [mlir][gpu] Adding the ELF section to the NVVMTargetAttr, to propagate to the gpu.binary Op Dec 10, 2024
Copy link

github-actions bot commented Dec 10, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Contributor

@fabianmcg fabianmcg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for pushing for this, overall supportive of the idea. However, the section doesn't belong in a target attribute but rather the object attribute.

I thought then it would be easy to edit a DictionaryAttr but it turns out that these attributes are immutable and need to be passed during the construction of the gpu.binary Op.

It's possible to update the attribute, you just need to construct it again.

The other option is adding a pass option gpu-module-to-binary to create gpu.object with the correct section from the start.

Also, if this is for flang, I would suggest adding a OffloadingLLVMTranslationAttrInterface attribute instead of using SelectObjectAttr, see: https://github.com/llvm/llvm-project/blob/main/mlir/include/mlir/Dialect/GPU/IR/CompilationAttrInterfaces.td#L100-L142

@Renaud-K
Copy link
Contributor Author

Renaud-K commented Dec 10, 2024

The SelectObjectAttr does everything we need. Having our own implementation of OffloadingLLVMTranslationAttrInterface would lead to a lot of cut-and-paste. This PR is mostly to avoid the cut-and-paste of CUFDialectLLVMIRTranslationInterface that we need downstream to set the ELF section.

My goal is to leverage as much upstream code as possible.

It's possible to update the attribute, you just need to construct it again.

Would this mean that I would have to replace the gpu.binary op with a new one?
The blobs attached to them can be huge. Are we confident we will not be duplicating memory passing one to the next?

@Renaud-K
Copy link
Contributor Author

The other option is adding a pass option gpu-module-to-binary to create gpu.object with the correct section from the start.

I like this approach. Thank you. I will look into it.

@fabianmcg
Copy link
Contributor

The SelectObjectAttr does everything we need. Having our own implementation of OffloadingLLVMTranslationAttrInterface would lead to a lot of cut-and-paste.

The reason I mention a new attribute, is because a new attribute would be able to handle cuda binary registration for using CUDA RT.

Would this mean that I would have to replace the gpu.binary op with a new one?

No, you would only need to update the attributes.

The blobs attached to them can be huge. Are we confident we will not be duplicating memory passing one to the next?

It shouldn't #gpu.object stores a string attribute to the binary precisely to avoid duplicating the blob https://github.com/llvm/llvm-project/blob/main/mlir/include/mlir/Dialect/GPU/IR/CompilationAttrs.td#L226

@Renaud-K Renaud-K changed the title [mlir][gpu] Adding the ELF section to the NVVMTargetAttr, to propagate to the gpu.binary Op [mlir][gpu] Adding ELF section option to the gpu-module-to-binary pass Dec 10, 2024
@Renaud-K Renaud-K requested a review from ftynse December 10, 2024 23:28
Copy link
Contributor

@clementval clementval left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me Renaud!

@Renaud-K
Copy link
Contributor Author

Can I proceed with these changes?

];
let options =
[Option<"toolkitPath", "toolkit", "std::string", [{""}], "Toolkit path.">,
ListOption<"linkFiles", "l", "std::string", "Extra files to link to.">,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't change the format, just add a new option.

Copy link
Contributor Author

@Renaud-K Renaud-K Dec 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

git-clang-format does that. Will the checks be happy if I undo it? I am afraid not since the diff is now on the radar. Shall I try? The version of clang, I am using, is the one from the build. Should I be using a different one?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised git clang-format actually touches .td files!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it does since the latest version

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The checks are still happy with the old format but it is probably just a matter of time until it fails there too.

Copy link
Contributor

@fabianmcg fabianmcg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

properties.push_back(
builder.getNamedAttr("O", builder.getI32IntegerAttr(target.getO())));

if (auto section = options.getELFSection(); !section.empty())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not: we need explicit type instead of auto when type isn't obvious


if (auto section = options.getELFSection(); !section.empty())
properties.push_back(
builder.getNamedAttr("section", builder.getStringAttr(section)));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe create a constant constexpr kSectionName = "section"

@Renaud-K Renaud-K merged commit 9919295 into llvm:main Dec 16, 2024
8 checks passed
@Renaud-K Renaud-K deleted the nvvm-attr-section branch January 28, 2025 01:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants