Skip to content
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

[X86] Respect code_model when determining if a global is small/large #74498

Merged
merged 1 commit into from
Dec 5, 2023

Conversation

aeubanks
Copy link
Contributor

@aeubanks aeubanks commented Dec 5, 2023

Using the GlobalVariable code_model property added in #72077.

code_model = "small" means the global should be treated as small regardless of the TargetMachine code model.
code_model = "large" means the global should be treated as large regardless of the TargetMachine code model.

Inferring small/large based on a known section name still takes precedence for correctness.

The intention is to use this for globals that are accessed very infrequently but also take up a lot of space in the binary to mitigate relocation overflows. Prime examples are globals that go in "__llvm_prf_names" for coverage/PGO instrumented builds and "asan_globals" for ASan builds.

@llvmbot
Copy link
Collaborator

llvmbot commented Dec 5, 2023

@llvm/pr-subscribers-backend-x86

Author: Arthur Eubanks (aeubanks)

Changes

Using the GlobalVariable code_model property added in #72077.

code_model = "small" means the global should be treated as small regardless of the TargetMachine code model.
code_model = "large" means the global should be treated as large regardless of the TargetMachine code model.

Inferring small/large based on a known section name still takes precedence for correctness.

The intention is to use this for globals that are accessed very infrequently but also take up a lot of space in the binary to mitigate relocation overflows. Prime examples are globals that go in "__llvm_prf_names" for coverage/PGO instrumented builds and "asan_globals" for ASan builds.


Full diff: https://github.com/llvm/llvm-project/pull/74498.diff

2 Files Affected:

  • (modified) llvm/lib/Target/TargetMachine.cpp (+10)
  • (modified) llvm/test/CodeGen/X86/code-model-elf-sections.ll (+11)
diff --git a/llvm/lib/Target/TargetMachine.cpp b/llvm/lib/Target/TargetMachine.cpp
index 8a14334551b00..ff496d29b3912 100644
--- a/llvm/lib/Target/TargetMachine.cpp
+++ b/llvm/lib/Target/TargetMachine.cpp
@@ -66,6 +66,16 @@ bool TargetMachine::isLargeGlobalObject(const GlobalObject *GO) const {
       return true;
   }
 
+  // For x86-64, we treat an explicit GlobalVariable small code model to mean
+  // that the global should be placed in a small section, and ditto for large.
+  // Well-known section names above take precedence for correctness.
+  if (auto CM = GV->getCodeModel()) {
+    if (*CM == CodeModel::Small)
+      return false;
+    if (*CM == CodeModel::Large)
+      return true;
+  }
+
   if (getCodeModel() == CodeModel::Medium ||
       getCodeModel() == CodeModel::Large) {
     const DataLayout &DL = GV->getParent()->getDataLayout();
diff --git a/llvm/test/CodeGen/X86/code-model-elf-sections.ll b/llvm/test/CodeGen/X86/code-model-elf-sections.ll
index f72880e172bdc..6c88791520413 100644
--- a/llvm/test/CodeGen/X86/code-model-elf-sections.ll
+++ b/llvm/test/CodeGen/X86/code-model-elf-sections.ll
@@ -24,6 +24,8 @@
 ; SMALL: .ldata {{.*}} WAl {{.*}}
 ; SMALL: .ldata.x {{.*}} WAl {{.*}}
 ; SMALL: .ldata0 {{.*}} WA {{.*}}
+; SMALL: force_small {{.*}} WA {{.*}}
+; SMALL: force_large {{.*}} WAl {{.*}}
 ; SMALL: foo {{.*}} WA {{.*}}
 ; SMALL: .bss {{.*}} WA {{.*}}
 ; SMALL: .lbss {{.*}} WAl {{.*}}
@@ -40,6 +42,8 @@
 ; SMALL-DS: .ldata.x {{.*}} WAl {{.*}}
 ; SMALL-DS: .ldata0 {{.*}} WA {{.*}}
 ; SMALL-DS: .data.data {{.*}} WA {{.*}}
+; SMALL-DS: force_small {{.*}} WA {{.*}}
+; SMALL-DS: force_large {{.*}} WAl {{.*}}
 ; SMALL-DS: foo {{.*}} WA {{.*}}
 ; SMALL-DS: .lbss {{.*}} WAl {{.*}}
 ; SMALL-DS: .bss.bss {{.*}} WA {{.*}}
@@ -55,6 +59,8 @@
 ; LARGE: .ldata {{.*}} WAl {{.*}}
 ; LARGE: .ldata.x {{.*}} WAl {{.*}}
 ; LARGE: .ldata0 {{.*}} WAl {{.*}}
+; LARGE: force_small {{.*}} WA {{.*}}
+; LARGE: force_large {{.*}} WAl {{.*}}
 ; LARGE: foo {{.*}} WAl {{.*}}
 ; LARGE: .bss {{.*}} WA {{.*}}
 ; LARGE: .lbss {{.*}} WAl {{.*}}
@@ -71,6 +77,8 @@
 ; LARGE-DS: .ldata.x {{.*}} WAl {{.*}}
 ; LARGE-DS: .ldata0 {{.*}} WAl {{.*}}
 ; LARGE-DS: .ldata.data {{.*}} WAl {{.*}}
+; LARGE-DS: force_small {{.*}} WA {{.*}}
+; LARGE-DS: force_large {{.*}} WAl {{.*}}
 ; LARGE-DS: foo {{.*}} WAl {{.*}}
 ; LARGE-DS: .bss {{.*}} WA {{.*}}
 ; LARGE-DS: .lbss.bss {{.*}} WAl {{.*}}
@@ -90,6 +98,9 @@ target triple = "x86_64--linux"
 @ldata_with_explicit_section2 = internal global [10 x i64] [i64 1, i64 2, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0], section ".ldata.x"
 @ldata_with_explicit_section0 = internal global [10 x i64] [i64 1, i64 2, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0], section ".ldata0"
 @data = internal global [10 x i64] [i64 1, i64 2, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0]
+@data_force_small = internal global [10 x i64] [i64 1, i64 2, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0], code_model "small", section "force_small"
+@data_force_large = internal global [10 x i64] [i64 1, i64 2, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0], code_model "large", section "force_large"
+@data_force_small_ldata = internal global [10 x i64] [i64 1, i64 2, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0], code_model "small", section ".ldata"
 @foo_with_explicit_section = internal global [10 x i64] [i64 1, i64 2, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0], section "foo"
 @bss_with_explicit_section = internal global [10 x i64] zeroinitializer, section ".bss"
 @lbss_with_explicit_section = internal global [10 x i64] zeroinitializer, section ".lbss"

@aeubanks aeubanks requested a review from rnk December 5, 2023 17:19
Using the GlobalVariable code_model property added in llvm#72077.

code_model = "small" means the global should be treated as small regardless of the TargetMachine code model.
code_model = "large" means the global should be treated as large regardless of the TargetMachine code model.

Inferring small/large based on a known section name still takes precedence for correctness.

The intention is to use this for globals that are accessed very infrequently but also take up a lot of space in the binary to mitigate relocation overflows. Prime examples are globals that go in "__llvm_prf_names" for coverage/PGO instrumented builds and "asan_globals" for ASan builds.
@aeubanks
Copy link
Contributor Author

aeubanks commented Dec 5, 2023

@heiher fyi

Copy link
Collaborator

@rnk rnk left a comment

Choose a reason for hiding this comment

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

Looks good, thanks!

@aeubanks aeubanks merged commit ddebce7 into llvm:main Dec 5, 2023
3 of 4 checks passed
@aeubanks aeubanks deleted the x86large branch December 5, 2023 18:38
aeubanks added a commit to aeubanks/llvm-project that referenced this pull request Dec 5, 2023
We'd like to make the asan_globals section large to make it not
contribute to relocation pressure since there are no direct PC32
references to it.

Following llvm#74498, we can do that by marking the code model for the
global explicitly large.

Without this change, asan_globals gets placed between .data and .bss.
With this change, it gets placed after .bss.
aeubanks added a commit that referenced this pull request Dec 7, 2023
We'd like to make the asan_globals section large to make it not
contribute to relocation pressure since there are no direct PC32
references to it.

Following #74498, we can do that by marking the code model for the
global explicitly large.

Without this change, asan_globals gets placed between .data and .bss.
With this change, it gets placed after .bss.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants