about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Brachet <abrachet@google.com>2022-12-05 06:37:21 +0000
committerAlex Brachet <abrachet@google.com>2022-12-07 16:32:59 +0000
commit5d88d3605339d61c81d16b29a1c01edf771a8fe6 (patch)
treed92eb7558dcc4b0b160505a586038eaa2efaa2d1
parent19c250aa1231f1e1b0953829e999e4862961207d (diff)
downloadrust-5d88d3605339d61c81d16b29a1c01edf771a8fe6.tar.gz
rust-5d88d3605339d61c81d16b29a1c01edf771a8fe6.zip
Don't internalize __llvm_profile_counter_bias
Currently, LLVM profiling runtime counter relocation cannot be
used by rust during LTO because symbols are being internalized
before all symbol information is known.

This mode makes LLVM emit a __llvm_profile_counter_bias symbol
which is referenced by the profiling initialization, which itself
is pulled in by the rust driver here [1].

It is enabled with -Cllvm-args=-runtime-counter-relocation for
platforms which are opt-in to this mode like Linux. On these
platforms there will be no link error, rather just surprising
behavior for a user which request runtime counter relocation.
The profiling runtime will not see that symbol go on as if it
were never there. On Fuchsia, the profiling runtime must have
this symbol which will cause a hard link error.

As an aside, I don't have enough context as to why rust's LTO
model is how it is. AFAICT, the internalize pass is only safe
to run at link time when all symbol information is actually
known, this being an example as to why. I think special casing
this symbol as a known one that LLVM can emit which should not
have it's visbility de-escalated should be fine given how
seldom this pattern of defining an undefined symbol to get
initilization code pulled in is. From a quick grep,
__llvm_profile_runtime is the only symbol that rustc does this
for.

[1] https://github.com/rust-lang/rust/blob/0265a3e93bf1b89d97cae113ed214954d5c35e22/compiler/rustc_codegen_ssa/src/back/linker.rs#L598
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs4
-rw-r--r--src/test/codegen/pgo-counter-bias.rs10
2 files changed, 14 insertions, 0 deletions
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index 3fa21355b7f..551663bfbbd 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -133,6 +133,10 @@ fn prepare_lto(
         }
     }
 
+    // __llvm_profile_counter_bias is pulled in at link time by an undefined reference to
+    // __llvm_profile_runtime, therefore we won't know until link time if this symbol
+    // should have default visibility.
+    symbols_below_threshold.push(CString::new("__llvm_profile_counter_bias").unwrap());
     Ok((symbols_below_threshold, upstream_modules))
 }
 
diff --git a/src/test/codegen/pgo-counter-bias.rs b/src/test/codegen/pgo-counter-bias.rs
new file mode 100644
index 00000000000..28caa7f4aa3
--- /dev/null
+++ b/src/test/codegen/pgo-counter-bias.rs
@@ -0,0 +1,10 @@
+// Test that __llvm_profile_counter_bias does not get internalized by lto.
+
+// ignore-macos -runtime-counter-relocation not honored on Mach-O
+// compile-flags: -Cprofile-generate -Cllvm-args=-runtime-counter-relocation -Clto=fat
+// needs-profiler-support
+// no-prefer-dynamic
+
+// CHECK: @__llvm_profile_counter_bias = {{.*}}global
+
+pub fn main() {}