/// possibly referenced from inline assembly, etc).
unsigned NoRename : 1;
+ /// Indicate if a function contains inline assembly (which is opaque),
+ /// that may reference a local value. This is used to prevent importing
+ /// of this function, since we can't promote and rename the uses of the
+ /// local in the inline assembly. Use a flag rather than bloating the
+ /// summary with references to every possible local value in the
+ /// llvm.used set.
+ unsigned HasInlineAsmMaybeReferencingInternal : 1;
+
/// Indicate if the function is not viable to inline.
unsigned IsNotViableToInline : 1;
/// Convenience Constructors
explicit GVFlags(GlobalValue::LinkageTypes Linkage, bool NoRename,
+ bool HasInlineAsmMaybeReferencingInternal,
bool IsNotViableToInline)
: Linkage(Linkage), NoRename(NoRename),
+ HasInlineAsmMaybeReferencingInternal(
+ HasInlineAsmMaybeReferencingInternal),
IsNotViableToInline(IsNotViableToInline) {}
GVFlags(const GlobalValue &GV)
- : Linkage(GV.getLinkage()), NoRename(GV.hasSection()) {
+ : Linkage(GV.getLinkage()), NoRename(GV.hasSection()),
+ HasInlineAsmMaybeReferencingInternal(false) {
IsNotViableToInline = false;
if (const auto *F = dyn_cast<Function>(&GV))
// Inliner doesn't handle variadic functions.
/// possibly referenced from inline assembly, etc).
void setNoRename() { Flags.NoRename = true; }
+ /// Return true if this global value possibly references another value
+ /// that can't be renamed.
+ bool hasInlineAsmMaybeReferencingInternal() const {
+ return Flags.HasInlineAsmMaybeReferencingInternal;
+ }
+
+ /// Flag that this global value possibly references another value that
+ /// can't be renamed.
+ void setHasInlineAsmMaybeReferencingInternal() {
+ Flags.HasInlineAsmMaybeReferencingInternal = true;
+ }
+
/// Record a reference from this global value to the global value identified
/// by \p RefGUID.
void addRefEdge(GlobalValue::GUID RefGUID) { RefEdgeList.push_back(RefGUID); }
static void computeFunctionSummary(ModuleSummaryIndex &Index, const Module &M,
const Function &F, BlockFrequencyInfo *BFI,
ProfileSummaryInfo *PSI,
- SmallPtrSetImpl<GlobalValue *> &LocalsUsed) {
+ bool HasLocalsInUsed) {
// 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();
+ bool HasInlineAsmMaybeReferencingInternal = false;
SmallPtrSet<const User *, 8> Visited;
for (const BasicBlock &BB : F)
for (const Instruction &I : BB) {
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).
+ // assembly, conservatively mark the function as possibly referencing
+ // a local value from inline assembly to ensure we don't export a
+ // reference (which would require renaming and promotion of the
+ // referenced value).
if (HasLocalsInUsed && CI && CI->isInlineAsm())
- RefEdges.insert(LocalsUsed.begin(), LocalsUsed.end());
+ HasInlineAsmMaybeReferencingInternal = true;
auto *CalledValue = CS.getCalledValue();
auto *CalledFunction = CS.getCalledFunction();
FuncSummary->addCallGraphEdges(CallGraphEdges);
FuncSummary->addCallGraphEdges(IndirectCallEdges);
FuncSummary->addRefEdges(RefEdges);
+ if (HasInlineAsmMaybeReferencingInternal)
+ FuncSummary->setHasInlineAsmMaybeReferencingInternal();
Index.addGlobalValueSummary(F.getName(), std::move(FuncSummary));
}
BFI = BFIPtr.get();
}
- computeFunctionSummary(Index, M, F, BFI, PSI, LocalsUsed);
+ computeFunctionSummary(Index, M, F, BFI, PSI, !LocalsUsed.empty());
}
// Compute summaries for all variables defined in module, and save in the
RawFlags = RawFlags >> 4;
bool NoRename = RawFlags & 0x1;
bool IsNotViableToInline = RawFlags & 0x2;
- return GlobalValueSummary::GVFlags(Linkage, NoRename, IsNotViableToInline);
+ bool HasInlineAsmMaybeReferencingInternal = RawFlags & 0x4;
+ return GlobalValueSummary::GVFlags(Linkage, NoRename,
+ HasInlineAsmMaybeReferencingInternal,
+ IsNotViableToInline);
}
static GlobalValue::VisibilityTypes getDecodedVisibility(unsigned Val) {
RawFlags |= Flags.NoRename; // bool
RawFlags |= (Flags.IsNotViableToInline << 1);
+ RawFlags |= (Flags.HasInlineAsmMaybeReferencingInternal << 2);
// Linkage don't need to be remapped at that time for the summary. Any future
// change to the getEncodedLinkage() function will need to be taken into
// account here as well.
// Check references (and potential calls) in the same module. If the current
// value references a global that can't be externally referenced it is not
- // eligible for import.
+ // eligible for import. First check the flag set when we have possible
+ // opaque references (e.g. inline asm calls), then check the call and
+ // reference sets.
+ if (Summary.hasInlineAsmMaybeReferencingInternal())
+ return false;
bool AllRefsCanBeExternallyReferenced =
llvm::all_of(Summary.refs(), [&](const ValueInfo &VI) {
return canBeExternallyReferenced(Index, VI.getGUID());