Skip to content

Commit e313bc8

Browse files
[StaticDataLayout] Factor out a helper function for section prefix eligibility and use it in both optimizer and codegen (llvm#162348)
This change introduces new helper functions to check if a global variable is eligible for section prefix annotation. This shared logic is used by both MemProfUse and StaticDataSplitter to avoid annotating ineligible variables. This is the 2nd patch as a split of llvm#155337
1 parent 068e179 commit e313bc8

File tree

7 files changed

+119
-37
lines changed

7 files changed

+119
-37
lines changed

llvm/include/llvm/Analysis/StaticDataProfileInfo.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,24 @@
1010

1111
namespace llvm {
1212

13+
namespace memprof {
14+
// Represents the eligibility status of a global variable for section prefix
15+
// annotation. Other than AnnotationOk, each enum value indicates a specific
16+
// reason for ineligibility.
17+
enum class AnnotationKind : uint8_t {
18+
AnnotationOK,
19+
DeclForLinker,
20+
ExplicitSection,
21+
ReservedName,
22+
};
23+
/// Returns the annotation kind of the global variable \p GV.
24+
AnnotationKind getAnnotationKind(const GlobalVariable &GV);
25+
26+
/// Returns true if the annotation kind of the global variable \p GV is
27+
/// AnnotationOK.
28+
bool IsAnnotationOK(const GlobalVariable &GV);
29+
} // namespace memprof
30+
1331
/// A class that holds the constants that represent static data and their
1432
/// profile information and provides methods to operate on them.
1533
class StaticDataProfileInfo {

llvm/lib/Analysis/StaticDataProfileInfo.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,46 @@
66
#include "llvm/ProfileData/InstrProf.h"
77

88
using namespace llvm;
9+
10+
namespace llvm {
11+
namespace memprof {
12+
// Returns true iff the global variable has custom section either by
13+
// __attribute__((section("name")))
14+
// (https://clang.llvm.org/docs/AttributeReference.html#section-declspec-allocate)
15+
// or #pragma clang section directives
16+
// (https://clang.llvm.org/docs/LanguageExtensions.html#specifying-section-names-for-global-objects-pragma-clang-section).
17+
static bool hasExplicitSectionName(const GlobalVariable &GVar) {
18+
if (GVar.hasSection())
19+
return true;
20+
21+
auto Attrs = GVar.getAttributes();
22+
if (Attrs.hasAttribute("bss-section") || Attrs.hasAttribute("data-section") ||
23+
Attrs.hasAttribute("relro-section") ||
24+
Attrs.hasAttribute("rodata-section"))
25+
return true;
26+
return false;
27+
}
28+
29+
AnnotationKind getAnnotationKind(const GlobalVariable &GV) {
30+
if (GV.isDeclarationForLinker())
31+
return AnnotationKind::DeclForLinker;
32+
// Skip 'llvm.'-prefixed global variables conservatively because they are
33+
// often handled specially,
34+
StringRef Name = GV.getName();
35+
if (Name.starts_with("llvm."))
36+
return AnnotationKind::ReservedName;
37+
// Respect user-specified custom data sections.
38+
if (hasExplicitSectionName(GV))
39+
return AnnotationKind::ExplicitSection;
40+
return AnnotationKind::AnnotationOK;
41+
}
42+
43+
bool IsAnnotationOK(const GlobalVariable &GV) {
44+
return getAnnotationKind(GV) == AnnotationKind::AnnotationOK;
45+
}
46+
} // namespace memprof
47+
} // namespace llvm
48+
949
void StaticDataProfileInfo::addConstantProfileCount(
1050
const Constant *C, std::optional<uint64_t> Count) {
1151
if (!Count) {

llvm/lib/CodeGen/StaticDataAnnotator.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ bool StaticDataAnnotator::runOnModule(Module &M) {
7575

7676
bool Changed = false;
7777
for (auto &GV : M.globals()) {
78-
if (GV.isDeclarationForLinker())
78+
if (!llvm::memprof::IsAnnotationOK(GV))
7979
continue;
8080

8181
// The implementation below assumes prior passes don't set section prefixes,

llvm/lib/CodeGen/StaticDataSplitter.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,8 @@ StaticDataSplitter::getConstant(const MachineOperand &Op,
130130
if (Op.isGlobal()) {
131131
// Find global variables with local linkage.
132132
const GlobalVariable *GV = getLocalLinkageGlobalVariable(Op.getGlobal());
133-
// Skip 'llvm.'-prefixed global variables conservatively because they are
134-
// often handled specially, and skip those not in static data
135-
// sections.
136-
if (!GV || GV->getName().starts_with("llvm.") ||
133+
// Skip those not eligible for annotation or not in static data sections.
134+
if (!GV || !llvm::memprof::IsAnnotationOK(*GV) ||
137135
!inStaticDataSection(*GV, TM))
138136
return nullptr;
139137
return GV;

llvm/lib/Transforms/Instrumentation/MemProfUse.cpp

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "llvm/ADT/StringRef.h"
1818
#include "llvm/Analysis/MemoryProfileInfo.h"
1919
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
20+
#include "llvm/Analysis/StaticDataProfileInfo.h"
2021
#include "llvm/Analysis/TargetLibraryInfo.h"
2122
#include "llvm/IR/DiagnosticInfo.h"
2223
#include "llvm/IR/Function.h"
@@ -194,6 +195,30 @@ static bool isAllocationWithHotColdVariant(const Function *Callee,
194195
}
195196
}
196197

198+
static void HandleUnsupportedAnnotationKinds(GlobalVariable &GVar,
199+
AnnotationKind Kind) {
200+
assert(Kind != llvm::memprof::AnnotationKind::AnnotationOK &&
201+
"Should not handle AnnotationOK here");
202+
SmallString<32> Reason;
203+
switch (Kind) {
204+
case llvm::memprof::AnnotationKind::ExplicitSection:
205+
++NumOfMemProfExplicitSectionGlobalVars;
206+
Reason.append("explicit section name");
207+
break;
208+
case llvm::memprof::AnnotationKind::DeclForLinker:
209+
Reason.append("linker declaration");
210+
break;
211+
case llvm::memprof::AnnotationKind::ReservedName:
212+
Reason.append("name starts with `llvm.`");
213+
break;
214+
default:
215+
llvm_unreachable("Unexpected annotation kind");
216+
}
217+
LLVM_DEBUG(dbgs() << "Skip annotation for " << GVar.getName() << " due to "
218+
<< Reason << ".\n");
219+
return;
220+
}
221+
197222
struct AllocMatchInfo {
198223
uint64_t TotalSize = 0;
199224
AllocationType AllocType = AllocationType::None;
@@ -775,23 +800,6 @@ PreservedAnalyses MemProfUsePass::run(Module &M, ModuleAnalysisManager &AM) {
775800
return PreservedAnalyses::none();
776801
}
777802

778-
// Returns true iff the global variable has custom section either by
779-
// __attribute__((section("name")))
780-
// (https://clang.llvm.org/docs/AttributeReference.html#section-declspec-allocate)
781-
// or #pragma clang section directives
782-
// (https://clang.llvm.org/docs/LanguageExtensions.html#specifying-section-names-for-global-objects-pragma-clang-section).
783-
static bool hasExplicitSectionName(const GlobalVariable &GVar) {
784-
if (GVar.hasSection())
785-
return true;
786-
787-
auto Attrs = GVar.getAttributes();
788-
if (Attrs.hasAttribute("bss-section") || Attrs.hasAttribute("data-section") ||
789-
Attrs.hasAttribute("relro-section") ||
790-
Attrs.hasAttribute("rodata-section"))
791-
return true;
792-
return false;
793-
}
794-
795803
bool MemProfUsePass::annotateGlobalVariables(
796804
Module &M, const memprof::DataAccessProfData *DataAccessProf) {
797805
if (!AnnotateStaticDataSectionPrefix || M.globals().empty())
@@ -817,13 +825,9 @@ bool MemProfUsePass::annotateGlobalVariables(
817825
for (GlobalVariable &GVar : M.globals()) {
818826
assert(!GVar.getSectionPrefix().has_value() &&
819827
"GVar shouldn't have section prefix yet");
820-
if (GVar.isDeclarationForLinker())
821-
continue;
822-
823-
if (hasExplicitSectionName(GVar)) {
824-
++NumOfMemProfExplicitSectionGlobalVars;
825-
LLVM_DEBUG(dbgs() << "Global variable " << GVar.getName()
826-
<< " has explicit section name. Skip annotating.\n");
828+
auto Kind = llvm::memprof::getAnnotationKind(GVar);
829+
if (Kind != llvm::memprof::AnnotationKind::AnnotationOK) {
830+
HandleUnsupportedAnnotationKinds(GVar, Kind);
827831
continue;
828832
}
829833

@@ -833,7 +837,6 @@ bool MemProfUsePass::annotateGlobalVariables(
833837
// TODO: Track string content hash in the profiles and compute it inside the
834838
// compiler to categeorize the hotness string literals.
835839
if (Name.starts_with(".str")) {
836-
837840
LLVM_DEBUG(dbgs() << "Skip annotating string literal " << Name << "\n");
838841
continue;
839842
}

llvm/test/CodeGen/X86/global-variable-partition.ll

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,23 +106,31 @@ target triple = "x86_64-unknown-linux-gnu"
106106
; UNIQ-NEXT: .section .data.unlikely.,"aw",@progbits,unique,8
107107
; AGG-NEXT: .section .data.unlikely.,"aw",@progbits
108108

109+
;; The `.section` directive is omitted for .data with -unique-section-names=false.
110+
; See MCSectionELF::shouldOmitSectionDirective for the implementation details.
111+
109112
; For @data_with_unknown_hotness
110113
; SYM: .type .Ldata_with_unknown_hotness,@object # @data_with_unknown_hotness
111114
; SYM: .section .data..Ldata_with_unknown_hotness,"aw",@progbits
112115
; UNIQ: .section .data,"aw",@progbits,unique,9
113-
; The `.section` directive is omitted for .data with -unique-section-names=false.
114-
; See MCSectionELF::shouldOmitSectionDirective for the implementation details.
116+
115117
; AGG: .data
116118
; COMMON: .Ldata_with_unknown_hotness:
117119

118-
; For @hot_data_custom_bar_section
119-
; It has an explicit section attribute 'var' and shouldn't have hot or unlikely suffix.
120+
; For variables that are not eligible for section prefix annotation
120121
; COMMON: .type hot_data_custom_bar_section,@object
121122
; SYM-NEXT: .section bar,"aw",@progbits
122123
; SYM: hot_data_custom_bar_section
123124
; UNIQ: .section bar,"aw",@progbits
124125
; AGG: .section bar,"aw",@progbits
125126

127+
; SYM: .section .data.llvm.fake_var,"aw"
128+
; UNIQ: .section .data,"aw"
129+
; AGG: .data
130+
131+
;; No section for linker declaration
132+
; COMMON-NOT: qux
133+
126134
@.str = private unnamed_addr constant [5 x i8] c"hot\09\00", align 1
127135
@.str.1 = private unnamed_addr constant [10 x i8] c"%d\09%d\09%d\0A\00", align 1
128136
@hot_relro_array = internal constant [2 x ptr] [ptr @bss2, ptr @data3]
@@ -137,6 +145,8 @@ target triple = "x86_64-unknown-linux-gnu"
137145
@data3 = internal global i32 3
138146
@data_with_unknown_hotness = private global i32 5
139147
@hot_data_custom_bar_section = internal global i32 101 #0
148+
@llvm.fake_var = internal global i32 123
149+
@qux = external global i64
140150

141151
define void @cold_func(i32 %0) !prof !15 {
142152
%2 = load i32, ptr @cold_bss

llvm/test/Transforms/PGOProfile/data-access-profile.ll

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@
3131
; LOG: Global variable var2.llvm.125 is annotated as hot
3232
; LOG: Global variable bar is not annotated
3333
; LOG: Global variable foo is annotated as unlikely
34-
; LOG: Global variable var3 has explicit section name. Skip annotating.
35-
; LOG: Global variable var4 has explicit section name. Skip annotating.
34+
; LOG: Skip annotation for var3 due to explicit section name.
35+
; LOG: Skip annotation for var4 due to explicit section name.
36+
; LOG: Skip annotation for llvm.fake_var due to name starts with `llvm.`.
37+
; LOG: Skip annotation for qux due to linker declaration.
3638

3739
;; String literals are not annotated.
3840
; IR: @.str = unnamed_addr constant [5 x i8] c"abcde"
@@ -54,6 +56,11 @@
5456
; IR-NEXT: @var3 = constant [2 x i32] [i32 12345, i32 6789], section "sec1"
5557
; IR-NEXT: @var4 = constant [1 x i64] [i64 98765] #0
5658

59+
; IR: @llvm.fake_var = global i32 123
60+
; IR-NOT: !section_prefix
61+
; IR: @qux = external global i64
62+
; IR-NOT: !section_prefix
63+
5764
; IR: attributes #0 = { "rodata-section"="sec2" }
5865

5966
; IR: !0 = !{!"section_prefix", !"hot"}
@@ -112,11 +119,14 @@ target triple = "x86_64-unknown-linux-gnu"
112119
@foo = global i8 2
113120
@var3 = constant [2 x i32][i32 12345, i32 6789], section "sec1"
114121
@var4 = constant [1 x i64][i64 98765] #0
122+
@llvm.fake_var = global i32 123
123+
@qux = external global i64
115124

116125
define i32 @func() {
117126
%a = load i32, ptr @var1
118127
%b = load i32, ptr @var2.llvm.125
119-
%ret = call i32 (...) @func_taking_arbitrary_param(i32 %a, i32 %b)
128+
%c = load i32, ptr @llvm.fake_var
129+
%ret = call i32 (...) @func_taking_arbitrary_param(i32 %a, i32 %b, i32 %c)
120130
ret i32 %ret
121131
}
122132

@@ -136,5 +146,8 @@ target triple = "x86_64-unknown-linux-gnu"
136146
@foo = global i8 2
137147
@var3 = constant [2 x i32][i32 12345, i32 6789], section "sec1"
138148
@var4 = constant [1 x i64][i64 98765] #0
149+
@llvm.fake_var = global i32 123
150+
@qux = external global i64
151+
139152

140153
attributes #0 = { "rodata-section"="sec2" }

0 commit comments

Comments
 (0)