[llvm] [NFCI][Globals]For GlobalObjects, add updateSectionPrefix and change setSectionPrefix to handle empty strings (PR #158460)

Mingming Liu via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 15 19:55:52 PDT 2025


https://github.com/mingmingl-llvm updated https://github.com/llvm/llvm-project/pull/158460

>From 887e2705800396e09ab7462817043b727291666f Mon Sep 17 00:00:00 2001
From: mingmingl <mingmingl at google.com>
Date: Sat, 13 Sep 2025 23:16:50 -0700
Subject: [PATCH 1/3] [NFCI][Globals]Add GlobalObjects::updateSectionPrefix and
 change setSectionPrefix to handle empty strings

---
 llvm/include/llvm/IR/GlobalObject.h    |  7 ++-
 llvm/lib/IR/Globals.cpp                | 17 ++++++
 llvm/unittests/IR/CMakeLists.txt       |  1 +
 llvm/unittests/IR/GlobalObjectTest.cpp | 81 ++++++++++++++++++++++++++
 4 files changed, 105 insertions(+), 1 deletion(-)
 create mode 100644 llvm/unittests/IR/GlobalObjectTest.cpp

diff --git a/llvm/include/llvm/IR/GlobalObject.h b/llvm/include/llvm/IR/GlobalObject.h
index 08a02b42bdc14..740d7fb9bc41f 100644
--- a/llvm/include/llvm/IR/GlobalObject.h
+++ b/llvm/include/llvm/IR/GlobalObject.h
@@ -121,9 +121,14 @@ class GlobalObject : public GlobalValue {
   /// appropriate default object file section.
   LLVM_ABI void setSection(StringRef S);
 
-  /// Set the section prefix for this global object.
+  /// Set the section prefix for this global object. If \p Prefix is empty,
+  /// the section prefix metadata will be cleared if it exists.
   LLVM_ABI void setSectionPrefix(StringRef Prefix);
 
+  /// If \p Prefix is different from existing prefix, update section prefix.
+  /// Returns true if an update happens and false otherwise.
+  LLVM_ABI bool updateSectionPrefix(StringRef Prefix);
+
   /// Get the section prefix for this global object.
   LLVM_ABI std::optional<StringRef> getSectionPrefix() const;
 
diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp
index 11d33e262fecb..0731fcbde106a 100644
--- a/llvm/lib/IR/Globals.cpp
+++ b/llvm/lib/IR/Globals.cpp
@@ -289,11 +289,28 @@ void GlobalObject::setSection(StringRef S) {
 }
 
 void GlobalObject::setSectionPrefix(StringRef Prefix) {
+  if (Prefix.empty()) {
+    setMetadata(LLVMContext::MD_section_prefix, nullptr);
+    return;
+  }
   MDBuilder MDB(getContext());
   setMetadata(LLVMContext::MD_section_prefix,
               MDB.createGlobalObjectSectionPrefix(Prefix));
 }
 
+bool GlobalObject::updateSectionPrefix(StringRef Prefix) {
+  auto MD = getMetadata(LLVMContext::MD_section_prefix);
+  StringRef ExistingPrefix; // Empty by default.
+  if (MD != nullptr)
+    ExistingPrefix = cast<MDString>(MD->getOperand(1))->getString();
+
+  if (ExistingPrefix != Prefix) {
+    setSectionPrefix(Prefix);
+    return true;
+  }
+  return false;
+}
+
 std::optional<StringRef> GlobalObject::getSectionPrefix() const {
   if (MDNode *MD = getMetadata(LLVMContext::MD_section_prefix)) {
     [[maybe_unused]] StringRef MDName =
diff --git a/llvm/unittests/IR/CMakeLists.txt b/llvm/unittests/IR/CMakeLists.txt
index 8b7bd3997ea27..d62ce66ef9d34 100644
--- a/llvm/unittests/IR/CMakeLists.txt
+++ b/llvm/unittests/IR/CMakeLists.txt
@@ -28,6 +28,7 @@ add_llvm_unittest(IRTests
   DominatorTreeBatchUpdatesTest.cpp
   DroppedVariableStatsIRTest.cpp
   FunctionTest.cpp
+  GlobalObjectTest.cpp
   PassBuilderCallbacksTest.cpp
   IRBuilderTest.cpp
   InstructionsTest.cpp
diff --git a/llvm/unittests/IR/GlobalObjectTest.cpp b/llvm/unittests/IR/GlobalObjectTest.cpp
new file mode 100644
index 0000000000000..0732b6f6691f1
--- /dev/null
+++ b/llvm/unittests/IR/GlobalObjectTest.cpp
@@ -0,0 +1,81 @@
+//===- GlobalObjectTest.cpp - Global object unit tests --------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/GlobalObject.h"
+#include "llvm-c/Core.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/SourceMgr.h"
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+using namespace llvm;
+namespace {
+
+using testing::Eq;
+using testing::Optional;
+using testing::StrEq;
+
+static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
+  SMDiagnostic Err;
+  std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
+  if (!Mod)
+    Err.print("GlobalObjectTests", errs());
+  return Mod;
+}
+
+static LLVMContext C;
+static std::unique_ptr<Module> M;
+
+class GlobalObjectTest : public testing::Test {
+public:
+static void SetUpTestSuite()  {
+   
+    M = parseIR(C, R"(
+ at foo = global i32 3, !section_prefix !0
+ at bar = global i32 0
+
+!0 = !{!"section_prefix", !"hot"}
+)");
+
+  }
+
+};
+
+TEST_F(GlobalObjectTest, SectionPrefix) {
+    GlobalVariable* Foo = M->getGlobalVariable("foo");
+    
+    // Initial section prefix is hot.
+    ASSERT_NE(Foo, nullptr);
+    ASSERT_THAT(Foo->getSectionPrefix(), Optional(StrEq("hot")));
+
+    // No actual update.
+    EXPECT_FALSE(Foo->updateSectionPrefix("hot"));
+
+    // Update prefix from hot to unlikely.
+    Foo->setSectionPrefix("unlikely");
+    EXPECT_THAT(Foo->getSectionPrefix(), Optional(StrEq("unlikely")));
+    
+    // Update prefix to empty is the same as clear.
+    Foo->setSectionPrefix("");
+    EXPECT_THAT(Foo->getSectionPrefix(), Eq(std::nullopt));
+
+    GlobalVariable* Bar = M->getGlobalVariable("bar");
+
+    // Initial section prefix is empty.
+    ASSERT_NE(Bar, nullptr);
+    ASSERT_THAT(Bar->getSectionPrefix(),  Eq(std::nullopt));
+ 
+    // No actual update.
+    EXPECT_FALSE(Bar->updateSectionPrefix(""));
+
+    // Update from empty to hot.
+    EXPECT_TRUE(Bar->updateSectionPrefix("hot"));
+    EXPECT_THAT(Bar->getSectionPrefix(), Optional(StrEq("hot")));
+}
+
+} // namespace

>From 314696a7adc95e47f4937e6a218b081e29b1d709 Mon Sep 17 00:00:00 2001
From: mingmingl <mingmingl at google.com>
Date: Sat, 13 Sep 2025 23:19:47 -0700
Subject: [PATCH 2/3] run clang format

---
 llvm/unittests/IR/GlobalObjectTest.cpp | 57 ++++++++++++--------------
 1 file changed, 26 insertions(+), 31 deletions(-)

diff --git a/llvm/unittests/IR/GlobalObjectTest.cpp b/llvm/unittests/IR/GlobalObjectTest.cpp
index 0732b6f6691f1..26949ae3a39fa 100644
--- a/llvm/unittests/IR/GlobalObjectTest.cpp
+++ b/llvm/unittests/IR/GlobalObjectTest.cpp
@@ -11,11 +11,10 @@
 #include "llvm/AsmParser/Parser.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/SourceMgr.h"
-#include "gtest/gtest.h"
 #include "gmock/gmock.h"
+#include "gtest/gtest.h"
 using namespace llvm;
 namespace {
-
 using testing::Eq;
 using testing::Optional;
 using testing::StrEq;
@@ -33,49 +32,45 @@ static std::unique_ptr<Module> M;
 
 class GlobalObjectTest : public testing::Test {
 public:
-static void SetUpTestSuite()  {
-   
+  static void SetUpTestSuite() {
     M = parseIR(C, R"(
 @foo = global i32 3, !section_prefix !0
 @bar = global i32 0
 
 !0 = !{!"section_prefix", !"hot"}
 )");
-
   }
-
 };
 
 TEST_F(GlobalObjectTest, SectionPrefix) {
-    GlobalVariable* Foo = M->getGlobalVariable("foo");
-    
-    // Initial section prefix is hot.
-    ASSERT_NE(Foo, nullptr);
-    ASSERT_THAT(Foo->getSectionPrefix(), Optional(StrEq("hot")));
+  GlobalVariable *Foo = M->getGlobalVariable("foo");
 
-    // No actual update.
-    EXPECT_FALSE(Foo->updateSectionPrefix("hot"));
+  // Initial section prefix is hot.
+  ASSERT_NE(Foo, nullptr);
+  ASSERT_THAT(Foo->getSectionPrefix(), Optional(StrEq("hot")));
 
-    // Update prefix from hot to unlikely.
-    Foo->setSectionPrefix("unlikely");
-    EXPECT_THAT(Foo->getSectionPrefix(), Optional(StrEq("unlikely")));
-    
-    // Update prefix to empty is the same as clear.
-    Foo->setSectionPrefix("");
-    EXPECT_THAT(Foo->getSectionPrefix(), Eq(std::nullopt));
+  // No actual update.
+  EXPECT_FALSE(Foo->updateSectionPrefix("hot"));
 
-    GlobalVariable* Bar = M->getGlobalVariable("bar");
+  // Update prefix from hot to unlikely.
+  Foo->setSectionPrefix("unlikely");
+  EXPECT_THAT(Foo->getSectionPrefix(), Optional(StrEq("unlikely")));
 
-    // Initial section prefix is empty.
-    ASSERT_NE(Bar, nullptr);
-    ASSERT_THAT(Bar->getSectionPrefix(),  Eq(std::nullopt));
- 
-    // No actual update.
-    EXPECT_FALSE(Bar->updateSectionPrefix(""));
+  // Update prefix to empty is the same as clear.
+  Foo->setSectionPrefix("");
+  EXPECT_THAT(Foo->getSectionPrefix(), Eq(std::nullopt));
 
-    // Update from empty to hot.
-    EXPECT_TRUE(Bar->updateSectionPrefix("hot"));
-    EXPECT_THAT(Bar->getSectionPrefix(), Optional(StrEq("hot")));
-}
+  GlobalVariable *Bar = M->getGlobalVariable("bar");
+
+  // Initial section prefix is empty.
+  ASSERT_NE(Bar, nullptr);
+  ASSERT_THAT(Bar->getSectionPrefix(), Eq(std::nullopt));
 
+  // No actual update.
+  EXPECT_FALSE(Bar->updateSectionPrefix(""));
+
+  // Update from empty to hot.
+  EXPECT_TRUE(Bar->updateSectionPrefix("hot"));
+  EXPECT_THAT(Bar->getSectionPrefix(), Optional(StrEq("hot")));
+}
 } // namespace

>From b894f774a874f822598e02faf8a04a1d985d9c63 Mon Sep 17 00:00:00 2001
From: mingmingl <mingmingl at google.com>
Date: Mon, 15 Sep 2025 15:52:09 -0700
Subject: [PATCH 3/3] incorporate review feedback

---
 llvm/include/llvm/IR/GlobalObject.h    |  3 ++-
 llvm/lib/IR/Globals.cpp                |  7 +++----
 llvm/unittests/IR/GlobalObjectTest.cpp | 11 ++++++++---
 3 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/llvm/include/llvm/IR/GlobalObject.h b/llvm/include/llvm/IR/GlobalObject.h
index 740d7fb9bc41f..99d20c5520033 100644
--- a/llvm/include/llvm/IR/GlobalObject.h
+++ b/llvm/include/llvm/IR/GlobalObject.h
@@ -125,7 +125,8 @@ class GlobalObject : public GlobalValue {
   /// the section prefix metadata will be cleared if it exists.
   LLVM_ABI void setSectionPrefix(StringRef Prefix);
 
-  /// If \p Prefix is different from existing prefix, update section prefix.
+  /// If \p Prefix is different from existing prefix, update section prefix;
+  /// if \p Prefix is empty, an update clears the existing metadata.
   /// Returns true if an update happens and false otherwise.
   LLVM_ABI bool updateSectionPrefix(StringRef Prefix);
 
diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp
index 0731fcbde106a..fad8d6083a4ae 100644
--- a/llvm/lib/IR/Globals.cpp
+++ b/llvm/lib/IR/Globals.cpp
@@ -299,10 +299,9 @@ void GlobalObject::setSectionPrefix(StringRef Prefix) {
 }
 
 bool GlobalObject::updateSectionPrefix(StringRef Prefix) {
-  auto MD = getMetadata(LLVMContext::MD_section_prefix);
-  StringRef ExistingPrefix; // Empty by default.
-  if (MD != nullptr)
-    ExistingPrefix = cast<MDString>(MD->getOperand(1))->getString();
+  StringRef ExistingPrefix;
+  if (std::optional<StringRef> MaybePrefix = getSectionPrefix())
+    ExistingPrefix = *MaybePrefix;
 
   if (ExistingPrefix != Prefix) {
     setSectionPrefix(Prefix);
diff --git a/llvm/unittests/IR/GlobalObjectTest.cpp b/llvm/unittests/IR/GlobalObjectTest.cpp
index 26949ae3a39fa..52984bf09e34e 100644
--- a/llvm/unittests/IR/GlobalObjectTest.cpp
+++ b/llvm/unittests/IR/GlobalObjectTest.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/IR/GlobalObject.h"
-#include "llvm-c/Core.h"
 #include "llvm/AsmParser/Parser.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/SourceMgr.h"
@@ -56,8 +55,9 @@ TEST_F(GlobalObjectTest, SectionPrefix) {
   Foo->setSectionPrefix("unlikely");
   EXPECT_THAT(Foo->getSectionPrefix(), Optional(StrEq("unlikely")));
 
-  // Update prefix to empty is the same as clear.
+  // Set prefix to empty is the same as clear.
   Foo->setSectionPrefix("");
+  // Test that section prefix is cleared.
   EXPECT_THAT(Foo->getSectionPrefix(), Eq(std::nullopt));
 
   GlobalVariable *Bar = M->getGlobalVariable("bar");
@@ -66,11 +66,16 @@ TEST_F(GlobalObjectTest, SectionPrefix) {
   ASSERT_NE(Bar, nullptr);
   ASSERT_THAT(Bar->getSectionPrefix(), Eq(std::nullopt));
 
-  // No actual update.
+  // Teset that update method returns false since Bar doesn't have prefix
+  // metadata.
   EXPECT_FALSE(Bar->updateSectionPrefix(""));
 
   // Update from empty to hot.
   EXPECT_TRUE(Bar->updateSectionPrefix("hot"));
   EXPECT_THAT(Bar->getSectionPrefix(), Optional(StrEq("hot")));
+
+  // Teset that update method returns true and section prefix is cleared.
+  EXPECT_TRUE(Bar->updateSectionPrefix(""));
+  EXPECT_THAT(Bar->getSectionPrefix(), Eq(std::nullopt));
 }
 } // namespace



More information about the llvm-commits mailing list