-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[NFCI][Globals] In GlobalObjects::setSectionPrefix, do conditional update if existing prefix is not equivalent to the new one. Returns whether prefix changed. #158460
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
Conversation
…ectionPrefix to handle empty strings
Foo->setSectionPrefix("unlikely"); | ||
EXPECT_THAT(Foo->getSectionPrefix(), Optional(StrEq("unlikely"))); | ||
|
||
// Update prefix to empty is the same as clear. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/Update/Set since we have a method called Update too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
//===----------------------------------------------------------------------===// | ||
|
||
#include "llvm/IR/GlobalObject.h" | ||
#include "llvm-c/Core.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder what this header is used for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The headers are copied from FunctionTest.cpp. I removed the unused ones now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The title and summary are both mechanical. Maybe add a 1 sentence description of why this change is needed?
llvm/lib/IR/Globals.cpp
Outdated
} | ||
|
||
bool GlobalObject::updateSectionPrefix(StringRef Prefix) { | ||
auto MD = getMetadata(LLVMContext::MD_section_prefix); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use getSectionPrefix instead? It does some assertion checking that could be useful.
Also, does it make sense to just make this the default behavior of setSectionPrefix?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use getSectionPrefix instead? It does some assertion checking that could be useful.
done.
does it make sense to just make this the default behavior of setSectionPrefix?
Implementation wise, the update method currently calls the set method (the other way around). Technically, no existing caller of 'set' depends on the behavior that 'set' method will overwrite, so either way (with a brief comment on the function decl in header) is fine imo. Doing it the current way will avoid affecting (fwiw) existing user in codegen prepare to set function section prefix though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does it make sense to just make this the default behavior of setSectionPrefix?
Implementation wise, the update method currently calls the set method (the other way around). Technically, no existing caller of 'set' depends on the behavior that 'set' method will overwrite, so either way (with a brief comment on the function decl in header) is fine imo. Doing it the current way will avoid affecting (fwiw) existing user in codegen prepare to set function section prefix though.
How would existing code be affected if setSectionPrefix was changed to do the update? What is the current behavior if setSectionPrefix is used in a context where a different section prefix already exists?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would existing code be affected if setSectionPrefix was changed to do the update?
The existing code calls 'set' once for function (callsite) or global variable (callsite). If setSectionPrefix is changed to call update, the outcome is the same, except that they get additional comparisons (and makes a difference to compile time in cases where additional comparisons are not needed, like for functions).
What is the current behavior if setSectionPrefix is used in a context where a different section prefix already exists?
It'll overwrite the existing section prefix per implementation, although existing callers calls this function once, so either an update or not works (in terms of the outcome).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per offline discussion, the question is more about why not changing setSectionPrefix
in place rather than calling update
inside set
.
Technically changing setSectionPrefix
is definitely an option, but I previously chose to add update
to not affect existing callers.
That said, compile-time changes are trivial enough, and all existing use cases also tracks whether a change happens on the IR/MIR, so I just update the PR to change setSectionPrefix
in place for simplicity. One other notable change is that codegenprepare previously doesn't track function prefix change as EverMadeChange
, but this patch changes it to be. PTAL, thanks!
@llvm/pr-subscribers-llvm-transforms @llvm/pr-subscribers-llvm-ir Author: Mingming Liu (mingmingl-llvm) ChangesThis PR introduces two main changes to GlobalObject with unit test coverage.
This is a split of #155337 Full diff: https://github.com/llvm/llvm-project/pull/158460.diff 4 Files Affected:
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..26949ae3a39fa
--- /dev/null
+++ b/llvm/unittests/IR/GlobalObjectTest.cpp
@@ -0,0 +1,76 @@
+//===- 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 "gmock/gmock.h"
+#include "gtest/gtest.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"(
+@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")));
+
+ // 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
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The title and summary are both mechanical. Maybe add a 1 sentence description of why this change is needed?
Sure! The updated PR description points to the use case.
Also clicked 'ready for review' to make this non-draft. Forgot to do this when I requested reviews before.
Foo->setSectionPrefix("unlikely"); | ||
EXPECT_THAT(Foo->getSectionPrefix(), Optional(StrEq("unlikely"))); | ||
|
||
// Update prefix to empty is the same as clear. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
//===----------------------------------------------------------------------===// | ||
|
||
#include "llvm/IR/GlobalObject.h" | ||
#include "llvm-c/Core.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The headers are copied from FunctionTest.cpp. I removed the unused ones now.
llvm/lib/IR/Globals.cpp
Outdated
} | ||
|
||
bool GlobalObject::updateSectionPrefix(StringRef Prefix) { | ||
auto MD = getMetadata(LLVMContext::MD_section_prefix); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use getSectionPrefix instead? It does some assertion checking that could be useful.
done.
does it make sense to just make this the default behavior of setSectionPrefix?
Implementation wise, the update method currently calls the set method (the other way around). Technically, no existing caller of 'set' depends on the behavior that 'set' method will overwrite, so either way (with a brief comment on the function decl in header) is fine imo. Doing it the current way will avoid affecting (fwiw) existing user in codegen prepare to set function section prefix though.
Did you push your changes yet? I don't see the updated diff. |
Sorry! This is pushed now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lgtm
EXPECT_TRUE(Bar->updateSectionPrefix("hot")); | ||
EXPECT_THAT(Bar->getSectionPrefix(), Optional(StrEq("hot"))); | ||
|
||
// Teset that update method returns true and section prefix is cleared. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm but comment needs a slight fix as noted below.
llvm/include/llvm/IR/GlobalObject.h
Outdated
|
||
/// Set the section prefix for this global object. | ||
LLVM_ABI void setSectionPrefix(StringRef Prefix); | ||
/// If existing prefix is different from \p Prefix is different, set it to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
redundant "different"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for the catch! fixed it.
In both windows and linux, the failed tests are irrelevant. Going to merge this change.
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/144/builds/35592 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/11/builds/24109 Here is the relevant piece of the build log for the reference
|
…, do conditional update if existing prefix is not equivalent to the new one. Returns whether prefix changed." (#159159) Reverts llvm/llvm-project#158460 due to buildbot failures
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/27/builds/16139 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/3/builds/22025 Here is the relevant piece of the build log for the reference
|
…ix, do conditional update if existing prefix is not equivalent to the new one. Returns whether prefix changed." (#159161) This is a reland of llvm/llvm-project#158460 Test failures are gone once I undo the changes in codegenprepare.
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/23/builds/13935 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/198/builds/7911 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/168/builds/16188 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/145/builds/9807 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/160/builds/24995 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/180/builds/25135 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/108/builds/17751 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/125/builds/10397 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/169/builds/14972 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/161/builds/7898 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/95/builds/18270 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/202/builds/3365 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/72/builds/15098 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/39/builds/7898 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/127/builds/4747 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/49/builds/2239 Here is the relevant piece of the build log for the reference
|
Before this change,
setSectionPrefix
overwrites existing section prefix with new one unconditionally.After this change,
setSectionPrefix
checks for equivalences, updates conditionally and returns whether an update happens.Update the existing callers to make use of the return value. PR 155337 is a motivating use case whether the 'update' semantic is needed.