[llvm] e6f7637 - EntryExitInstrumenter: skip available_externally linkage
via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 3 09:25:11 PST 2025
Author: Fangrui Song
Date: 2025-01-03T09:25:08-08:00
New Revision: e6f76378c20bebec85f66c1574bb6bb928a79025
URL: https://github.com/llvm/llvm-project/commit/e6f76378c20bebec85f66c1574bb6bb928a79025
DIFF: https://github.com/llvm/llvm-project/commit/e6f76378c20bebec85f66c1574bb6bb928a79025.diff
LOG: EntryExitInstrumenter: skip available_externally linkage
gnu::always_inline functions, which lower to available_externally, may
not have definitions external to the module. -finstrument-function
family options instrumentating the function (which takes the function
address) may lead to a linker error if the function is not optimized
out, e.g.
```
// -std=c++17 or above with libstdc++
#include <string>
std::string str;
int main() {}
```
Simplified reproduce:
```
template <typename T>
struct A {
[[gnu::always_inline]] T bar(T a) { return a * 2; }
};
extern template class A<int>;
int main(int argc, char **argv) {
return A<int>().bar(argc);
}
```
GCC's -finstrument-function instrumentation skips such functions
(https://gcc.gnu.org/PR78333). Let's skip such functions
(available_externally) as well.
Fix #50742
Pull Request: https://github.com/llvm/llvm-project/pull/121452
Added:
Modified:
llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp
llvm/test/Transforms/EntryExitInstrumenter/mcount.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp b/llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp
index 5b33edd51cffa6..d47f1b4253b541 100644
--- a/llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp
+++ b/llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp
@@ -103,6 +103,12 @@ static bool runOnFunction(Function &F, bool PostInlining) {
if (F.hasFnAttribute(Attribute::Naked))
return false;
+ // available_externally functions may not have definitions external to the
+ // module (e.g. gnu::always_inline). Instrumenting them might lead to linker
+ // errors if they are optimized out. Skip them like GCC.
+ if (F.hasAvailableExternallyLinkage())
+ return false;
+
StringRef EntryAttr = PostInlining ? "instrument-function-entry-inlined"
: "instrument-function-entry";
diff --git a/llvm/test/Transforms/EntryExitInstrumenter/mcount.ll b/llvm/test/Transforms/EntryExitInstrumenter/mcount.ll
index bd5f4c2b51a896..56ccfb9ed2e7e0 100644
--- a/llvm/test/Transforms/EntryExitInstrumenter/mcount.ll
+++ b/llvm/test/Transforms/EntryExitInstrumenter/mcount.ll
@@ -129,6 +129,13 @@ define void @naked() naked {
ret void
}
+define available_externally void @always_inline() {
+; CHECK-LABEL: define available_externally void @always_inline() {
+; CHECK-NEXT: ret void
+;
+ ret void
+}
+
; The attributes are "consumed" when the instrumentation is inserted.
; CHECK: attributes
; CHECK-NOT: instrument-function
More information about the llvm-commits
mailing list