[llvm] ed801ad - [Clang] Use metadata to make identifying embedded objects easier

Joseph Huber via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 7 09:20:52 PDT 2022


Author: Joseph Huber
Date: 2022-07-07T12:20:25-04:00
New Revision: ed801ad5e5fef76c4303d04fd8de21662b428bee

URL: https://github.com/llvm/llvm-project/commit/ed801ad5e5fef76c4303d04fd8de21662b428bee
DIFF: https://github.com/llvm/llvm-project/commit/ed801ad5e5fef76c4303d04fd8de21662b428bee.diff

LOG: [Clang] Use metadata to make identifying embedded objects easier

Currently we use the `embedBufferInModule` function to store binary
strings containing device offloading data inside the host object to
create a fatbinary. In the case of LTO, we need to extract this object
from the LLVM-IR. This patch adds a metadata node for the embedded
objects containing the embedded pointers and the sections they were
stored at. This should create a cleaner interface for identifying these
values.

In the future it may be worthwhile to also encode an `ID` in the
metadata corresponding to the object's special section type if relevant.
This would allow us to extract the data from an object file and LLVM-IR
using the same ID.

Reviewed By: jdoerfert

Differential Revision: https://reviews.llvm.org/D129033

Added: 
    

Modified: 
    clang/test/Frontend/embed-object.c
    clang/test/Frontend/embed-object.ll
    clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
    llvm/docs/LangRef.rst
    llvm/include/llvm/Transforms/Utils/ModuleUtils.h
    llvm/lib/Transforms/Utils/ModuleUtils.cpp

Removed: 
    


################################################################################
diff  --git a/clang/test/Frontend/embed-object.c b/clang/test/Frontend/embed-object.c
index ceb3378a60ab..364cb8aad193 100644
--- a/clang/test/Frontend/embed-object.c
+++ b/clang/test/Frontend/embed-object.c
@@ -4,3 +4,6 @@
 // CHECK: @llvm.compiler.used = appending global [1 x ptr] [ptr @[[OBJECT]]], section "llvm.metadata"
 
 void foo(void) {}
+
+// CHECK: !llvm.embedded.objects = !{![[METADATA:[0-9]+]]}
+// CHECK: ![[METADATA]] = !{ptr @[[OBJECT]], !".llvm.offloading"}

diff  --git a/clang/test/Frontend/embed-object.ll b/clang/test/Frontend/embed-object.ll
index 177ecdf7f8a3..bcb56fd55c73 100644
--- a/clang/test/Frontend/embed-object.ll
+++ b/clang/test/Frontend/embed-object.ll
@@ -13,3 +13,7 @@
 define i32 @foo() {
   ret i32 0
 }
+
+; CHECK: !llvm.embedded.objects = !{![[METADATA_1:[0-9]+]], ![[METADATA_2:[0-9]+]]}
+; CHECK: ![[METADATA_1]] = !{ptr @[[OBJECT_1]], !".llvm.offloading"}
+; CHECK: ![[METADATA_2]] = !{ptr @[[OBJECT_2]], !".llvm.offloading"}

diff  --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
index 3e935bcbd30a..e7214ebfde37 100644
--- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -366,12 +366,26 @@ Error extractFromBitcode(std::unique_ptr<MemoryBuffer> Buffer,
     return createStringError(inconvertibleErrorCode(),
                              "Failed to create module");
 
-  // Extract offloading data from globals with the `.llvm.offloading` section.
-  for (GlobalVariable &GV : M->globals()) {
-    if (!GV.hasSection() || !GV.getSection().equals(OFFLOAD_SECTION_MAGIC_STR))
+  // Extract offloading data from globals referenced by the
+  // `llvm.embedded.object` metadata with the `.llvm.offloading` section.
+  auto MD = M->getNamedMetadata("llvm.embedded.object");
+  if (!MD)
+    return Error::success();
+
+  for (const MDNode *Op : MD->operands()) {
+    if (Op->getNumOperands() < 2)
+      continue;
+
+    MDString *SectionID = dyn_cast<MDString>(Op->getOperand(1));
+    if (!SectionID || SectionID->getString() != OFFLOAD_SECTION_MAGIC_STR)
+      continue;
+
+    GlobalVariable *GV =
+        mdconst::dyn_extract_or_null<GlobalVariable>(Op->getOperand(0));
+    if (!GV)
       continue;
 
-    auto *CDS = dyn_cast<ConstantDataSequential>(GV.getInitializer());
+    auto *CDS = dyn_cast<ConstantDataSequential>(GV->getInitializer());
     if (!CDS)
       continue;
 

diff  --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 889eca2f438b..e74aaa8d77cf 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -7429,6 +7429,19 @@ Some optimisations are only when the entire LTO unit is present in the current
 module. This is represented by the ``LTOPostLink`` module flags metadata, which
 will be created with a value of ``1`` when LTO linking occurs.
 
+Embedded Objects Names Metadata
+===============================
+
+Offloading compilations need to embed device code into the host section table to
+create a fat binary. This metadata node references each global that will be
+embedded in the module. The primary use for this is to make referencing these
+globals more efficient in the IR. The metadata references nodes containing
+pointers to the global to be embedded followed by the section name it will be
+stored at::
+
+    !llvm.embedded.objects = !{!0}
+    !0 = !{ptr @object, !".section"}
+
 Automatic Linker Flags Named Metadata
 =====================================
 

diff  --git a/llvm/include/llvm/Transforms/Utils/ModuleUtils.h b/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
index 85263fc00bc3..335cf7acc2f7 100644
--- a/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
@@ -109,7 +109,8 @@ void filterDeadComdatFunctions(
 std::string getUniqueModuleId(Module *M);
 
 /// Embed the memory buffer \p Buf into the module \p M as a global using the
-/// specified section name.
+/// specified section name. Also provide a metadata entry to identify it in the
+/// module using the same section name.
 void embedBufferInModule(Module &M, MemoryBufferRef Buf, StringRef SectionName,
                          Align Alignment = Align(1));
 

diff  --git a/llvm/lib/Transforms/Utils/ModuleUtils.cpp b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
index 5120ade70e16..a3529bfd2e43 100644
--- a/llvm/lib/Transforms/Utils/ModuleUtils.cpp
+++ b/llvm/lib/Transforms/Utils/ModuleUtils.cpp
@@ -275,5 +275,12 @@ void llvm::embedBufferInModule(Module &M, MemoryBufferRef Buf,
   GV->setSection(SectionName);
   GV->setAlignment(Alignment);
 
+  LLVMContext &Ctx = M.getContext();
+  NamedMDNode *MD = M.getOrInsertNamedMetadata("llvm.embedded.objects");
+  Metadata *MDVals[] = {ConstantAsMetadata::get(GV),
+                        MDString::get(Ctx, SectionName)};
+
+  MD->addOperand(llvm::MDNode::get(Ctx, MDVals));
+
   appendToCompilerUsed(M, GV);
 }


        


More information about the llvm-commits mailing list