Skip to content

Commit 027bccc

Browse files
[NFCI][Globals] In GlobalObjects::setSectionPrefix, do conditional update if existing prefix is not equivalent to the new one. Returns whether prefix changed. (#158460)
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](https://github.com/llvm/llvm-project/pull/155337/files#diff-cc0c67ac89807f4453f0cfea9164944a4650cd6873a468a0f907e7158818eae9) is a motivating use case whether the 'update' semantic is needed.
1 parent 95388b2 commit 027bccc

File tree

7 files changed

+105
-12
lines changed

7 files changed

+105
-12
lines changed

llvm/include/llvm/IR/GlobalObject.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,10 @@ class GlobalObject : public GlobalValue {
121121
/// appropriate default object file section.
122122
LLVM_ABI void setSection(StringRef S);
123123

124-
/// Set the section prefix for this global object.
125-
LLVM_ABI void setSectionPrefix(StringRef Prefix);
124+
/// If existing prefix is different from \p Prefix, set it to \p Prefix. If \p
125+
/// Prefix is empty, the set clears the existing metadata. Returns true if
126+
/// section prefix changed and false otherwise.
127+
LLVM_ABI bool setSectionPrefix(StringRef Prefix);
126128

127129
/// Get the section prefix for this global object.
128130
LLVM_ABI std::optional<StringRef> getSectionPrefix() const;

llvm/lib/CodeGen/CodeGenPrepare.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -583,23 +583,23 @@ bool CodeGenPrepare::_run(Function &F) {
583583
// if requested.
584584
if (BBSectionsGuidedSectionPrefix && BBSectionsProfileReader &&
585585
BBSectionsProfileReader->isFunctionHot(F.getName())) {
586-
F.setSectionPrefix("hot");
586+
EverMadeChange |= F.setSectionPrefix("hot");
587587
} else if (ProfileGuidedSectionPrefix) {
588588
// The hot attribute overwrites profile count based hotness while profile
589589
// counts based hotness overwrite the cold attribute.
590590
// This is a conservative behabvior.
591591
if (F.hasFnAttribute(Attribute::Hot) ||
592592
PSI->isFunctionHotInCallGraph(&F, *BFI))
593-
F.setSectionPrefix("hot");
593+
EverMadeChange |= F.setSectionPrefix("hot");
594594
// If PSI shows this function is not hot, we will placed the function
595595
// into unlikely section if (1) PSI shows this is a cold function, or
596596
// (2) the function has a attribute of cold.
597597
else if (PSI->isFunctionColdInCallGraph(&F, *BFI) ||
598598
F.hasFnAttribute(Attribute::Cold))
599-
F.setSectionPrefix("unlikely");
599+
EverMadeChange |= F.setSectionPrefix("unlikely");
600600
else if (ProfileUnknownInSpecialSection && PSI->hasPartialSampleProfile() &&
601601
PSI->isFunctionHotnessUnknown(F))
602-
F.setSectionPrefix("unknown");
602+
EverMadeChange |= F.setSectionPrefix("unknown");
603603
}
604604

605605
/// This optimization identifies DIV instructions that can be

llvm/lib/CodeGen/StaticDataAnnotator.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,7 @@ bool StaticDataAnnotator::runOnModule(Module &M) {
9191
if (SectionPrefix.empty())
9292
continue;
9393

94-
GV.setSectionPrefix(SectionPrefix);
95-
Changed = true;
94+
Changed |= GV.setSectionPrefix(SectionPrefix);
9695
}
9796

9897
return Changed;

llvm/lib/IR/Globals.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,10 +288,22 @@ void GlobalObject::setSection(StringRef S) {
288288
setGlobalObjectFlag(HasSectionHashEntryBit, !S.empty());
289289
}
290290

291-
void GlobalObject::setSectionPrefix(StringRef Prefix) {
291+
bool GlobalObject::setSectionPrefix(StringRef Prefix) {
292+
StringRef ExistingPrefix;
293+
if (std::optional<StringRef> MaybePrefix = getSectionPrefix())
294+
ExistingPrefix = *MaybePrefix;
295+
296+
if (ExistingPrefix == Prefix)
297+
return false;
298+
299+
if (Prefix.empty()) {
300+
setMetadata(LLVMContext::MD_section_prefix, nullptr);
301+
return true;
302+
}
292303
MDBuilder MDB(getContext());
293304
setMetadata(LLVMContext::MD_section_prefix,
294305
MDB.createGlobalObjectSectionPrefix(Prefix));
306+
return true;
295307
}
296308

297309
std::optional<StringRef> GlobalObject::getSectionPrefix() const {

llvm/lib/Transforms/Instrumentation/MemProfUse.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -848,13 +848,12 @@ bool MemProfUsePass::annotateGlobalVariables(
848848
// So we just print out the static data section prefix in LLVM_DEBUG.
849849
if (Record && Record->AccessCount > 0) {
850850
++NumOfMemProfHotGlobalVars;
851-
GVar.setSectionPrefix("hot");
852-
Changed = true;
851+
Changed |= GVar.setSectionPrefix("hot");
853852
LLVM_DEBUG(dbgs() << "Global variable " << Name
854853
<< " is annotated as hot\n");
855854
} else if (DataAccessProf->isKnownColdSymbol(Name)) {
856855
++NumOfMemProfColdGlobalVars;
857-
GVar.setSectionPrefix("unlikely");
856+
Changed |= GVar.setSectionPrefix("unlikely");
858857
Changed = true;
859858
LLVM_DEBUG(dbgs() << "Global variable " << Name
860859
<< " is annotated as unlikely\n");

llvm/unittests/IR/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ add_llvm_unittest(IRTests
2828
DominatorTreeBatchUpdatesTest.cpp
2929
DroppedVariableStatsIRTest.cpp
3030
FunctionTest.cpp
31+
GlobalObjectTest.cpp
3132
PassBuilderCallbacksTest.cpp
3233
IRBuilderTest.cpp
3334
InstructionsTest.cpp
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//===- GlobalObjectTest.cpp - Global object unit tests --------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/IR/GlobalObject.h"
10+
#include "llvm/AsmParser/Parser.h"
11+
#include "llvm/IR/Module.h"
12+
#include "llvm/Support/SourceMgr.h"
13+
#include "gmock/gmock.h"
14+
#include "gtest/gtest.h"
15+
using namespace llvm;
16+
namespace {
17+
using testing::Eq;
18+
using testing::Optional;
19+
using testing::StrEq;
20+
21+
static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
22+
SMDiagnostic Err;
23+
std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
24+
if (!Mod)
25+
Err.print("GlobalObjectTests", errs());
26+
return Mod;
27+
}
28+
29+
static LLVMContext C;
30+
static std::unique_ptr<Module> M;
31+
32+
class GlobalObjectTest : public testing::Test {
33+
public:
34+
static void SetUpTestSuite() {
35+
M = parseIR(C, R"(
36+
@foo = global i32 3, !section_prefix !0
37+
@bar = global i32 0
38+
39+
!0 = !{!"section_prefix", !"hot"}
40+
)");
41+
}
42+
};
43+
44+
TEST_F(GlobalObjectTest, SectionPrefix) {
45+
GlobalVariable *Foo = M->getGlobalVariable("foo");
46+
47+
// Initial section prefix is hot.
48+
ASSERT_NE(Foo, nullptr);
49+
ASSERT_THAT(Foo->getSectionPrefix(), Optional(StrEq("hot")));
50+
51+
// Test that set method returns false since existing section prefix is hot.
52+
EXPECT_FALSE(Foo->setSectionPrefix("hot"));
53+
54+
// Set prefix from hot to unlikely.
55+
Foo->setSectionPrefix("unlikely");
56+
EXPECT_THAT(Foo->getSectionPrefix(), Optional(StrEq("unlikely")));
57+
58+
// Set prefix to empty is the same as clear.
59+
Foo->setSectionPrefix("");
60+
// Test that section prefix is cleared.
61+
EXPECT_THAT(Foo->getSectionPrefix(), Eq(std::nullopt));
62+
63+
GlobalVariable *Bar = M->getGlobalVariable("bar");
64+
65+
// Initial section prefix is empty.
66+
ASSERT_NE(Bar, nullptr);
67+
ASSERT_THAT(Bar->getSectionPrefix(), Eq(std::nullopt));
68+
69+
// Test that set method returns false since Bar doesn't have prefix metadata.
70+
EXPECT_FALSE(Bar->setSectionPrefix(""));
71+
72+
// Set from empty to hot.
73+
EXPECT_TRUE(Bar->setSectionPrefix("hot"));
74+
EXPECT_THAT(Bar->getSectionPrefix(), Optional(StrEq("hot")));
75+
76+
// Test that set method returns true and section prefix is cleared.
77+
EXPECT_TRUE(Bar->setSectionPrefix(""));
78+
EXPECT_THAT(Bar->getSectionPrefix(), Eq(std::nullopt));
79+
}
80+
} // namespace

0 commit comments

Comments
 (0)