Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions llvm/include/llvm/IR/GlobalObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,10 @@ class GlobalObject : public GlobalValue {
/// appropriate default object file section.
LLVM_ABI void setSection(StringRef S);

/// 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
Copy link
Contributor

Choose a reason for hiding this comment

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

redundant "different"

Copy link
Contributor Author

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.

/// \p Prefix. If \p Prefix is empty, the set clears the existing metadata.
/// Returns true if section prefix changed and false otherwise.
LLVM_ABI bool setSectionPrefix(StringRef Prefix);

/// Get the section prefix for this global object.
LLVM_ABI std::optional<StringRef> getSectionPrefix() const;
Expand Down
8 changes: 4 additions & 4 deletions llvm/lib/CodeGen/CodeGenPrepare.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -583,23 +583,23 @@ bool CodeGenPrepare::_run(Function &F) {
// if requested.
if (BBSectionsGuidedSectionPrefix && BBSectionsProfileReader &&
BBSectionsProfileReader->isFunctionHot(F.getName())) {
F.setSectionPrefix("hot");
EverMadeChange |= F.setSectionPrefix("hot");
} else if (ProfileGuidedSectionPrefix) {
// The hot attribute overwrites profile count based hotness while profile
// counts based hotness overwrite the cold attribute.
// This is a conservative behabvior.
if (F.hasFnAttribute(Attribute::Hot) ||
PSI->isFunctionHotInCallGraph(&F, *BFI))
F.setSectionPrefix("hot");
EverMadeChange |= F.setSectionPrefix("hot");
// If PSI shows this function is not hot, we will placed the function
// into unlikely section if (1) PSI shows this is a cold function, or
// (2) the function has a attribute of cold.
else if (PSI->isFunctionColdInCallGraph(&F, *BFI) ||
F.hasFnAttribute(Attribute::Cold))
F.setSectionPrefix("unlikely");
EverMadeChange |= F.setSectionPrefix("unlikely");
else if (ProfileUnknownInSpecialSection && PSI->hasPartialSampleProfile() &&
PSI->isFunctionHotnessUnknown(F))
F.setSectionPrefix("unknown");
EverMadeChange |= F.setSectionPrefix("unknown");
}

/// This optimization identifies DIV instructions that can be
Expand Down
3 changes: 1 addition & 2 deletions llvm/lib/CodeGen/StaticDataAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,7 @@ bool StaticDataAnnotator::runOnModule(Module &M) {
if (SectionPrefix.empty())
continue;

GV.setSectionPrefix(SectionPrefix);
Changed = true;
Changed |= GV.setSectionPrefix(SectionPrefix);
}

return Changed;
Expand Down
14 changes: 13 additions & 1 deletion llvm/lib/IR/Globals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,10 +288,22 @@ void GlobalObject::setSection(StringRef S) {
setGlobalObjectFlag(HasSectionHashEntryBit, !S.empty());
}

void GlobalObject::setSectionPrefix(StringRef Prefix) {
bool GlobalObject::setSectionPrefix(StringRef Prefix) {
StringRef ExistingPrefix;
if (std::optional<StringRef> MaybePrefix = getSectionPrefix())
ExistingPrefix = *MaybePrefix;

if (ExistingPrefix == Prefix)
return false;

if (Prefix.empty()) {
setMetadata(LLVMContext::MD_section_prefix, nullptr);
return true;
}
MDBuilder MDB(getContext());
setMetadata(LLVMContext::MD_section_prefix,
MDB.createGlobalObjectSectionPrefix(Prefix));
return true;
}

std::optional<StringRef> GlobalObject::getSectionPrefix() const {
Expand Down
5 changes: 2 additions & 3 deletions llvm/lib/Transforms/Instrumentation/MemProfUse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -848,13 +848,12 @@ bool MemProfUsePass::annotateGlobalVariables(
// So we just print out the static data section prefix in LLVM_DEBUG.
if (Record && Record->AccessCount > 0) {
++NumOfMemProfHotGlobalVars;
GVar.setSectionPrefix("hot");
Changed = true;
Changed |= GVar.setSectionPrefix("hot");
LLVM_DEBUG(dbgs() << "Global variable " << Name
<< " is annotated as hot\n");
} else if (DataAccessProf->isKnownColdSymbol(Name)) {
++NumOfMemProfColdGlobalVars;
GVar.setSectionPrefix("unlikely");
Changed |= GVar.setSectionPrefix("unlikely");
Changed = true;
LLVM_DEBUG(dbgs() << "Global variable " << Name
<< " is annotated as unlikely\n");
Expand Down
1 change: 1 addition & 0 deletions llvm/unittests/IR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ add_llvm_unittest(IRTests
DominatorTreeBatchUpdatesTest.cpp
DroppedVariableStatsIRTest.cpp
FunctionTest.cpp
GlobalObjectTest.cpp
PassBuilderCallbacksTest.cpp
IRBuilderTest.cpp
InstructionsTest.cpp
Expand Down
80 changes: 80 additions & 0 deletions llvm/unittests/IR/GlobalObjectTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//===- 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/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")));

// Test that set method returns false since existing section prefix is hot.
EXPECT_FALSE(Foo->setSectionPrefix("hot"));

// Set prefix from hot to unlikely.
Foo->setSectionPrefix("unlikely");
EXPECT_THAT(Foo->getSectionPrefix(), Optional(StrEq("unlikely")));

// 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");

// Initial section prefix is empty.
ASSERT_NE(Bar, nullptr);
ASSERT_THAT(Bar->getSectionPrefix(), Eq(std::nullopt));

// Test that set method returns false since Bar doesn't have prefix metadata.
EXPECT_FALSE(Bar->setSectionPrefix(""));

// Set from empty to hot.
EXPECT_TRUE(Bar->setSectionPrefix("hot"));
EXPECT_THAT(Bar->getSectionPrefix(), Optional(StrEq("hot")));

// Test that set method returns true and section prefix is cleared.
EXPECT_TRUE(Bar->setSectionPrefix(""));
EXPECT_THAT(Bar->getSectionPrefix(), Eq(std::nullopt));
}
} // namespace
Loading