|
120 | 120 | #include "llvm/Support/raw_ostream.h"
|
121 | 121 | #include "llvm/Transforms/IPO.h"
|
122 | 122 | #include "llvm/Transforms/Utils/FunctionComparator.h"
|
| 123 | +#include "llvm/Transforms/Utils/ModuleUtils.h" |
123 | 124 | #include <algorithm>
|
124 | 125 | #include <cassert>
|
125 | 126 | #include <iterator>
|
@@ -225,6 +226,9 @@ class MergeFunctions {
|
225 | 226 | /// analyzed again.
|
226 | 227 | std::vector<WeakTrackingVH> Deferred;
|
227 | 228 |
|
| 229 | + /// Set of values marked as used in llvm.used and llvm.compiler.used. |
| 230 | + SmallPtrSet<GlobalValue *, 4> Used; |
| 231 | + |
228 | 232 | #ifndef NDEBUG
|
229 | 233 | /// Checks the rules of order relation introduced among functions set.
|
230 | 234 | /// Returns true, if check has been passed, and false if failed.
|
@@ -407,6 +411,11 @@ static bool isEligibleForMerging(Function &F) {
|
407 | 411 | bool MergeFunctions::runOnModule(Module &M) {
|
408 | 412 | bool Changed = false;
|
409 | 413 |
|
| 414 | + SmallVector<GlobalValue *, 4> UsedV; |
| 415 | + collectUsedGlobalVariables(M, UsedV, /*CompilerUsed=*/false); |
| 416 | + collectUsedGlobalVariables(M, UsedV, /*CompilerUsed=*/true); |
| 417 | + Used.insert(UsedV.begin(), UsedV.end()); |
| 418 | + |
410 | 419 | // All functions in the module, ordered by hash. Functions with a unique
|
411 | 420 | // hash value are easily eliminated.
|
412 | 421 | std::vector<std::pair<FunctionComparator::FunctionHash, Function *>>
|
@@ -453,6 +462,7 @@ bool MergeFunctions::runOnModule(Module &M) {
|
453 | 462 | FnTree.clear();
|
454 | 463 | FNodesInTree.clear();
|
455 | 464 | GlobalNumbers.clear();
|
| 465 | + Used.clear(); |
456 | 466 |
|
457 | 467 | return Changed;
|
458 | 468 | }
|
@@ -825,7 +835,10 @@ void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
|
825 | 835 | // For better debugability, under MergeFunctionsPDI, we do not modify G's
|
826 | 836 | // call sites to point to F even when within the same translation unit.
|
827 | 837 | if (!G->isInterposable() && !MergeFunctionsPDI) {
|
828 |
| - if (G->hasGlobalUnnamedAddr()) { |
| 838 | + // Functions referred to by llvm.used/llvm.compiler.used are special: |
| 839 | + // there are uses of the symbol name that are not visible to LLVM, |
| 840 | + // usually from inline asm. |
| 841 | + if (G->hasGlobalUnnamedAddr() && !Used.contains(G)) { |
829 | 842 | // G might have been a key in our GlobalNumberState, and it's illegal
|
830 | 843 | // to replace a key in ValueMap<GlobalValue *> with a non-global.
|
831 | 844 | GlobalNumbers.erase(G);
|
|
0 commit comments