static void computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
const Function &F, BlockFrequencyInfo *BFI,
- ProfileSummaryInfo *PSI) {
+ ProfileSummaryInfo *PSI,
+ SmallPtrSetImpl<GlobalValue *> &LocalsUsed) {
// Summary not currently supported for anonymous functions, they should
// have been named.
assert(F.hasName());
DenseMap<GlobalValue::GUID, CalleeInfo> IndirectCallEdges;
DenseSet<const Value *> RefEdges;
ICallPromotionAnalysis ICallAnalysis;
+ bool HasLocalsInUsed = !LocalsUsed.empty();
SmallPtrSet<const User *, 8> Visited;
for (const BasicBlock &BB : F)
auto CS = ImmutableCallSite(&I);
if (!CS)
continue;
+
+ const auto *CI = dyn_cast<CallInst>(&I);
+ // Since we don't know exactly which local values are referenced in inline
+ // assembly, conservatively reference all of them from this function, to
+ // ensure we don't export a reference (which would require renaming and
+ // promotion).
+ if (HasLocalsInUsed && CI && CI->isInlineAsm())
+ RefEdges.insert(LocalsUsed.begin(), LocalsUsed.end());
+
auto *CalledValue = CS.getCalledValue();
auto *CalledFunction = CS.getCalledFunction();
// Check if this is an alias to a function. If so, get the
: CalleeInfo::HotnessType::Unknown;
CallGraphEdges[CalleeId].updateHotness(Hotness);
} else {
- const auto *CI = dyn_cast<CallInst>(&I);
// Skip inline assembly calls.
if (CI && CI->isInlineAsm())
continue;
std::function<BlockFrequencyInfo *(const Function &F)> GetBFICallback,
ProfileSummaryInfo *PSI) {
ModuleSummaryIndex Index;
- // Check if the module can be promoted, otherwise just disable importing from
- // it by not emitting any summary.
- // FIXME: we could still import *into* it most of the time.
- if (!moduleCanBeRenamedForThinLTO(M))
- return Index;
+
+ // Identify the local values in the llvm.used set, which should not be
+ // exported as they would then require renaming and promotion, but we
+ // may have opaque uses e.g. in inline asm.
+ SmallPtrSet<GlobalValue *, 8> Used;
+ collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
+ SmallPtrSet<GlobalValue *, 8> LocalsUsed;
+ for (auto *V : Used) {
+ if (V->hasLocalLinkage())
+ LocalsUsed.insert(V);
+ }
// Compute summaries for all functions defined in module, and save in the
// index.
BFI = BFIPtr.get();
}
- computeFunctionSummary(Index, M, F, BFI, PSI);
+ computeFunctionSummary(Index, M, F, BFI, PSI, LocalsUsed);
}
// Compute summaries for all variables defined in module, and save in the
for (const GlobalAlias &A : M.aliases())
computeAliasSummary(Index, A);
+ for (auto *V : LocalsUsed) {
+ auto *Summary = Index.getGlobalValueSummary(*V);
+ assert(Summary && "Missing summary for global value");
+ Summary->setNoRename();
+ }
+
return Index;
}
AU.addRequired<BlockFrequencyInfoWrapperPass>();
AU.addRequired<ProfileSummaryInfoWrapperPass>();
}
-
-bool llvm::moduleCanBeRenamedForThinLTO(const Module &M) {
- // We cannot currently promote or rename anything used in inline assembly,
- // which are not visible to the compiler. Detect a possible case by looking
- // for a llvm.used local value, in conjunction with an inline assembly call
- // in the module. Prevent importing of any modules containing these uses by
- // suppressing generation of the index. This also prevents importing
- // into this module, which is also necessary to avoid needing to rename
- // in case of a name clash between a local in this module and an imported
- // global.
- // FIXME: If we find we need a finer-grained approach of preventing promotion
- // and renaming of just the functions using inline assembly we will need to:
- // - Add flag in the function summaries to identify those with inline asm.
- // - Prevent importing of any functions with flag set.
- // - Prevent importing of any global function with the same name as a
- // function in current module that has the flag set.
- // - For any llvm.used value that is exported and promoted, add a private
- // alias to the original name in the current module (even if we don't
- // export the function using those values in inline asm, another function
- // with a reference could be exported).
- SmallPtrSet<GlobalValue *, 8> Used;
- collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
- bool LocalIsUsed =
- any_of(Used, [](GlobalValue *V) { return V->hasLocalLinkage(); });
- if (!LocalIsUsed)
- return true;
-
- // Walk all the instructions in the module and find if one is inline ASM
- auto HasInlineAsm = any_of(M, [](const Function &F) {
- return any_of(instructions(F), [](const Instruction &I) {
- const CallInst *CallI = dyn_cast<CallInst>(&I);
- if (!CallI)
- return false;
- return CallI->isInlineAsm();
- });
- });
- return !HasInlineAsm;
-}