summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp')
-rw-r--r--llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp34
1 files changed, 26 insertions, 8 deletions
diff --git a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
index f0cf5581ba8..d7c75049404 100644
--- a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
+++ b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
@@ -841,17 +841,35 @@ bool DevirtIndex::tryFindVirtualCallTargets(
std::vector<ValueInfo> &TargetsForSlot, const TypeIdCompatibleVtableInfo TIdInfo,
uint64_t ByteOffset) {
for (const TypeIdOffsetVtableInfo P : TIdInfo) {
- // VTable initializer should have only one summary, or all copies must be
- // linkonce/weak ODR.
+ // Ensure that we have at most one external linkage vtable initializer.
assert(P.VTableVI.getSummaryList().size() == 1 ||
- llvm::all_of(
+ llvm::count_if(
P.VTableVI.getSummaryList(),
[&](const std::unique_ptr<GlobalValueSummary> &Summary) {
- return GlobalValue::isLinkOnceODRLinkage(Summary->linkage()) ||
- GlobalValue::isWeakODRLinkage(Summary->linkage());
- }));
- const auto *VS = cast<GlobalVarSummary>(P.VTableVI.getSummaryList()[0].get());
- if (!P.VTableVI.getSummaryList()[0]->isLive())
+ return GlobalValue::isExternalLinkage(Summary->linkage());
+ }) <= 1);
+ // Find the first non-available_externally linkage vtable initializer.
+ // We can have multiple available_externally, linkonce_odr and weak_odr
+ // vtable initializers, however we want to skip available_externally as they
+ // do not have type metadata attached, and therefore the summary will not
+ // contain any vtable functions.
+ //
+ // Also, handle the case of same-named local Vtables with the same path
+ // and therefore the same GUID. This can happen if there isn't enough
+ // distinguishing path when compiling the source file. In that case we
+ // conservatively return false early.
+ const GlobalVarSummary *VS = nullptr;
+ bool LocalFound = false;
+ for (auto &S : P.VTableVI.getSummaryList()) {
+ if (GlobalValue::isLocalLinkage(S->linkage())) {
+ if (LocalFound)
+ return false;
+ LocalFound = true;
+ }
+ if (!GlobalValue::isAvailableExternallyLinkage(S->linkage()))
+ VS = cast<GlobalVarSummary>(S.get());
+ }
+ if (!VS->isLive())
continue;
for (auto VTP : VS->vTableFuncs()) {
if (VTP.VTableOffset != P.AddressPointOffset + ByteOffset)
OpenPOWER on IntegriCloud