2017-05-13 00:25:07 +02:00
|
|
|
//===- llvm/ModuleSummaryIndex.h - Module Summary Index ---------*- C++ -*-===//
|
2016-03-14 22:18:10 +01:00
|
|
|
//
|
2019-01-19 09:50:56 +01:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2016-03-14 22:18:10 +01:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
/// @file
|
2016-03-15 01:04:37 +01:00
|
|
|
/// ModuleSummaryIndex.h This file contains the declarations the classes that
|
|
|
|
/// hold the module index and summary for function importing.
|
2016-03-14 22:18:10 +01:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2016-03-15 01:04:37 +01:00
|
|
|
#ifndef LLVM_IR_MODULESUMMARYINDEX_H
|
|
|
|
#define LLVM_IR_MODULESUMMARYINDEX_H
|
2016-03-14 22:18:10 +01:00
|
|
|
|
2017-05-13 00:25:07 +02:00
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
2016-03-14 22:18:10 +01:00
|
|
|
#include "llvm/ADT/DenseMap.h"
|
2017-05-13 00:25:07 +02:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2017-06-06 13:49:48 +02:00
|
|
|
#include "llvm/ADT/SmallString.h"
|
2016-04-12 01:26:46 +02:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2016-03-14 22:18:10 +01:00
|
|
|
#include "llvm/ADT/StringMap.h"
|
2017-05-13 00:25:07 +02:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
[ThinLTO] Efficiency fix for writing type id records in per-module indexes
Summary:
In D49565/r337503, the type id record writing was fixed so that only
referenced type ids were emitted into each per-module index for ThinLTO
distributed builds. However, this still left an efficiency issue: each
per-module index checked all type ids for membership in the referenced
set, yielding O(M*N) performance (M indexes and N type ids).
Change the TypeIdMap in the summary to be indexed by GUID, to facilitate
correlating with type identifier GUIDs referenced in the function
summary TypeIdInfo structures. This allowed simplifying other
places where a map from type id GUID to type id map entry was previously
being used to aid this correlation.
Also fix AsmWriter code to handle the rare case of type id GUID
collision.
For a large internal application, this reduced the thin link time by
almost 15%.
Reviewers: pcc, vitalybuka
Subscribers: mehdi_amini, inglorion, steven_wu, dexonsmith, llvm-commits
Differential Revision: https://reviews.llvm.org/D51330
llvm-svn: 343021
2018-09-25 22:14:40 +02:00
|
|
|
#include "llvm/ADT/TinyPtrVector.h"
|
2017-05-13 00:25:07 +02:00
|
|
|
#include "llvm/IR/GlobalValue.h"
|
2017-06-06 13:49:48 +02:00
|
|
|
#include "llvm/IR/Module.h"
|
2018-06-26 04:29:08 +02:00
|
|
|
#include "llvm/Support/Allocator.h"
|
2018-01-25 20:27:17 +01:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
2018-02-22 20:44:08 +01:00
|
|
|
#include "llvm/Support/ScaledNumber.h"
|
2018-06-26 04:29:08 +02:00
|
|
|
#include "llvm/Support/StringSaver.h"
|
2017-05-13 00:25:07 +02:00
|
|
|
#include <algorithm>
|
2016-04-01 07:33:11 +02:00
|
|
|
#include <array>
|
2017-05-13 00:25:07 +02:00
|
|
|
#include <cassert>
|
|
|
|
#include <cstddef>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <map>
|
|
|
|
#include <memory>
|
2017-06-16 02:18:29 +02:00
|
|
|
#include <set>
|
2017-05-13 00:25:07 +02:00
|
|
|
#include <string>
|
|
|
|
#include <utility>
|
|
|
|
#include <vector>
|
2016-04-01 07:33:11 +02:00
|
|
|
|
2016-03-14 22:18:10 +01:00
|
|
|
namespace llvm {
|
|
|
|
|
2017-01-05 04:39:00 +01:00
|
|
|
namespace yaml {
|
2017-05-13 00:25:07 +02:00
|
|
|
|
2017-01-05 04:39:00 +01:00
|
|
|
template <typename T> struct MappingTraits;
|
2017-05-13 00:25:07 +02:00
|
|
|
|
|
|
|
} // end namespace yaml
|
2017-01-05 04:39:00 +01:00
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Class to accumulate and hold information about a callee.
|
2016-03-14 22:18:10 +01:00
|
|
|
struct CalleeInfo {
|
2017-07-07 23:01:00 +02:00
|
|
|
enum class HotnessType : uint8_t {
|
|
|
|
Unknown = 0,
|
|
|
|
Cold = 1,
|
|
|
|
None = 2,
|
|
|
|
Hot = 3,
|
|
|
|
Critical = 4
|
|
|
|
};
|
[thinlto] Basic thinlto fdo heuristic
Summary:
This patch improves thinlto importer
by importing 3x larger functions that are called from hot block.
I compared performance with the trunk on spec, and there
were about 2% on povray and 3.33% on milc. These results seems
to be consistant and match the results Teresa got with her simple
heuristic. Some benchmarks got slower but I think they are just
noisy (mcf, xalancbmki, omnetpp)- running the benchmarks again with
more iterations to confirm. Geomean of all benchmarks including the noisy ones
were about +0.02%.
I see much better improvement on google branch with Easwaran patch
for pgo callsite inlining (the inliner actually inline those big functions)
Over all I see +0.5% improvement, and I get +8.65% on povray.
So I guess we will see much bigger change when Easwaran patch will land
(it depends on new pass manager), but it is still worth putting this to trunk
before it.
Implementation details changes:
- Removed CallsiteCount.
- ProfileCount got replaced by Hotness
- hot-import-multiplier is set to 3.0 for now,
didn't have time to tune it up, but I see that we get most of the interesting
functions with 3, so there is no much performance difference with higher, and
binary size doesn't grow as much as with 10.0.
Reviewers: eraman, mehdi_amini, tejohnson
Subscribers: mehdi_amini, llvm-commits
Differential Revision: https://reviews.llvm.org/D24638
llvm-svn: 282437
2016-09-26 22:37:32 +02:00
|
|
|
|
2018-01-25 20:27:17 +01:00
|
|
|
// The size of the bit-field might need to be adjusted if more values are
|
|
|
|
// added to HotnessType enum.
|
|
|
|
uint32_t Hotness : 3;
|
2018-02-22 20:44:08 +01:00
|
|
|
|
|
|
|
/// The value stored in RelBlockFreq has to be interpreted as the digits of
|
|
|
|
/// a scaled number with a scale of \p -ScaleShift.
|
2018-01-25 20:27:17 +01:00
|
|
|
uint32_t RelBlockFreq : 29;
|
2018-02-22 20:44:08 +01:00
|
|
|
static constexpr int32_t ScaleShift = 8;
|
2018-01-25 20:27:17 +01:00
|
|
|
static constexpr uint64_t MaxRelBlockFreq = (1 << 29) - 1;
|
|
|
|
|
|
|
|
CalleeInfo()
|
|
|
|
: Hotness(static_cast<uint32_t>(HotnessType::Unknown)), RelBlockFreq(0) {}
|
|
|
|
explicit CalleeInfo(HotnessType Hotness, uint64_t RelBF)
|
|
|
|
: Hotness(static_cast<uint32_t>(Hotness)), RelBlockFreq(RelBF) {}
|
[thinlto] Basic thinlto fdo heuristic
Summary:
This patch improves thinlto importer
by importing 3x larger functions that are called from hot block.
I compared performance with the trunk on spec, and there
were about 2% on povray and 3.33% on milc. These results seems
to be consistant and match the results Teresa got with her simple
heuristic. Some benchmarks got slower but I think they are just
noisy (mcf, xalancbmki, omnetpp)- running the benchmarks again with
more iterations to confirm. Geomean of all benchmarks including the noisy ones
were about +0.02%.
I see much better improvement on google branch with Easwaran patch
for pgo callsite inlining (the inliner actually inline those big functions)
Over all I see +0.5% improvement, and I get +8.65% on povray.
So I guess we will see much bigger change when Easwaran patch will land
(it depends on new pass manager), but it is still worth putting this to trunk
before it.
Implementation details changes:
- Removed CallsiteCount.
- ProfileCount got replaced by Hotness
- hot-import-multiplier is set to 3.0 for now,
didn't have time to tune it up, but I see that we get most of the interesting
functions with 3, so there is no much performance difference with higher, and
binary size doesn't grow as much as with 10.0.
Reviewers: eraman, mehdi_amini, tejohnson
Subscribers: mehdi_amini, llvm-commits
Differential Revision: https://reviews.llvm.org/D24638
llvm-svn: 282437
2016-09-26 22:37:32 +02:00
|
|
|
|
|
|
|
void updateHotness(const HotnessType OtherHotness) {
|
2018-01-25 20:27:17 +01:00
|
|
|
Hotness = std::max(Hotness, static_cast<uint32_t>(OtherHotness));
|
|
|
|
}
|
|
|
|
|
|
|
|
HotnessType getHotness() const { return HotnessType(Hotness); }
|
|
|
|
|
2018-02-22 20:44:08 +01:00
|
|
|
/// Update \p RelBlockFreq from \p BlockFreq and \p EntryFreq
|
|
|
|
///
|
|
|
|
/// BlockFreq is divided by EntryFreq and added to RelBlockFreq. To represent
|
|
|
|
/// fractional values, the result is represented as a fixed point number with
|
|
|
|
/// scale of -ScaleShift.
|
|
|
|
void updateRelBlockFreq(uint64_t BlockFreq, uint64_t EntryFreq) {
|
|
|
|
if (EntryFreq == 0)
|
|
|
|
return;
|
|
|
|
using Scaled64 = ScaledNumber<uint64_t>;
|
|
|
|
Scaled64 Temp(BlockFreq, ScaleShift);
|
|
|
|
Temp /= Scaled64::get(EntryFreq);
|
|
|
|
|
|
|
|
uint64_t Sum =
|
|
|
|
SaturatingAdd<uint64_t>(Temp.toInt<uint64_t>(), RelBlockFreq);
|
2018-01-25 20:27:17 +01:00
|
|
|
Sum = std::min(Sum, uint64_t(MaxRelBlockFreq));
|
|
|
|
RelBlockFreq = static_cast<uint32_t>(Sum);
|
2016-03-14 22:18:10 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-08-17 18:53:47 +02:00
|
|
|
inline const char *getHotnessName(CalleeInfo::HotnessType HT) {
|
|
|
|
switch (HT) {
|
|
|
|
case CalleeInfo::HotnessType::Unknown:
|
|
|
|
return "unknown";
|
|
|
|
case CalleeInfo::HotnessType::Cold:
|
|
|
|
return "cold";
|
|
|
|
case CalleeInfo::HotnessType::None:
|
|
|
|
return "none";
|
|
|
|
case CalleeInfo::HotnessType::Hot:
|
|
|
|
return "hot";
|
|
|
|
case CalleeInfo::HotnessType::Critical:
|
|
|
|
return "critical";
|
|
|
|
}
|
|
|
|
llvm_unreachable("invalid hotness");
|
|
|
|
}
|
|
|
|
|
2017-05-04 20:03:25 +02:00
|
|
|
class GlobalValueSummary;
|
2017-05-04 05:36:16 +02:00
|
|
|
|
2017-05-13 00:25:07 +02:00
|
|
|
using GlobalValueSummaryList = std::vector<std::unique_ptr<GlobalValueSummary>>;
|
2017-05-04 13:49:39 +02:00
|
|
|
|
2019-07-30 18:31:06 +02:00
|
|
|
struct alignas(8) GlobalValueSummaryInfo {
|
2018-01-22 14:35:40 +01:00
|
|
|
union NameOrGV {
|
2018-06-07 00:22:01 +02:00
|
|
|
NameOrGV(bool HaveGVs) {
|
|
|
|
if (HaveGVs)
|
2018-01-22 14:35:40 +01:00
|
|
|
GV = nullptr;
|
|
|
|
else
|
|
|
|
Name = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The GlobalValue corresponding to this summary. This is only used in
|
2018-06-07 00:22:01 +02:00
|
|
|
/// per-module summaries and when the IR is available. E.g. when module
|
|
|
|
/// analysis is being run, or when parsing both the IR and the summary
|
|
|
|
/// from assembly.
|
2018-01-22 14:35:40 +01:00
|
|
|
const GlobalValue *GV;
|
|
|
|
|
|
|
|
/// Summary string representation. This StringRef points to BC module
|
|
|
|
/// string table and is valid until module data is stored in memory.
|
|
|
|
/// This is guaranteed to happen until runThinLTOBackend function is
|
|
|
|
/// called, so it is safe to use this field during thin link. This field
|
|
|
|
/// is only valid if summary index was loaded from BC file.
|
|
|
|
StringRef Name;
|
|
|
|
} U;
|
|
|
|
|
2018-06-07 00:22:01 +02:00
|
|
|
GlobalValueSummaryInfo(bool HaveGVs) : U(HaveGVs) {}
|
2017-05-04 20:03:25 +02:00
|
|
|
|
|
|
|
/// List of global value summary structures for a particular value held
|
|
|
|
/// in the GlobalValueMap. Requires a vector in the case of multiple
|
|
|
|
/// COMDAT values of the same name.
|
|
|
|
GlobalValueSummaryList SummaryList;
|
2017-05-04 05:36:16 +02:00
|
|
|
};
|
|
|
|
|
2017-05-04 20:03:25 +02:00
|
|
|
/// Map from global value GUID to corresponding summary structures. Use a
|
|
|
|
/// std::map rather than a DenseMap so that pointers to the map's value_type
|
|
|
|
/// (which are used by ValueInfo) are not invalidated by insertion. Also it will
|
|
|
|
/// likely incur less overhead, as the value type is not very small and the size
|
|
|
|
/// of the map is unknown, resulting in inefficiencies due to repeated
|
|
|
|
/// insertions and resizing.
|
2017-05-13 00:25:07 +02:00
|
|
|
using GlobalValueSummaryMapTy =
|
|
|
|
std::map<GlobalValue::GUID, GlobalValueSummaryInfo>;
|
2017-05-04 20:03:25 +02:00
|
|
|
|
|
|
|
/// Struct that holds a reference to a particular GUID in a global value
|
|
|
|
/// summary.
|
|
|
|
struct ValueInfo {
|
2019-07-05 17:25:05 +02:00
|
|
|
enum Flags { HaveGV = 1, ReadOnly = 2, WriteOnly = 4 };
|
|
|
|
PointerIntPair<const GlobalValueSummaryMapTy::value_type *, 3, int>
|
2018-11-16 08:08:00 +01:00
|
|
|
RefAndFlags;
|
2017-05-13 00:25:07 +02:00
|
|
|
|
2017-05-04 20:03:25 +02:00
|
|
|
ValueInfo() = default;
|
2018-06-07 00:22:01 +02:00
|
|
|
ValueInfo(bool HaveGVs, const GlobalValueSummaryMapTy::value_type *R) {
|
2018-11-16 08:08:00 +01:00
|
|
|
RefAndFlags.setPointer(R);
|
|
|
|
RefAndFlags.setInt(HaveGVs);
|
2018-01-22 14:35:40 +01:00
|
|
|
}
|
2017-05-13 00:25:07 +02:00
|
|
|
|
2018-01-22 14:35:40 +01:00
|
|
|
operator bool() const { return getRef(); }
|
2017-05-04 20:03:25 +02:00
|
|
|
|
2018-01-22 14:35:40 +01:00
|
|
|
GlobalValue::GUID getGUID() const { return getRef()->first; }
|
|
|
|
const GlobalValue *getValue() const {
|
2018-06-07 00:22:01 +02:00
|
|
|
assert(haveGVs());
|
2018-01-22 14:35:40 +01:00
|
|
|
return getRef()->second.U.GV;
|
|
|
|
}
|
2017-05-13 00:25:07 +02:00
|
|
|
|
2017-05-04 20:03:25 +02:00
|
|
|
ArrayRef<std::unique_ptr<GlobalValueSummary>> getSummaryList() const {
|
2018-01-22 14:35:40 +01:00
|
|
|
return getRef()->second.SummaryList;
|
|
|
|
}
|
|
|
|
|
|
|
|
StringRef name() const {
|
2018-06-07 00:22:01 +02:00
|
|
|
return haveGVs() ? getRef()->second.U.GV->getName()
|
|
|
|
: getRef()->second.U.Name;
|
2018-01-22 14:35:40 +01:00
|
|
|
}
|
|
|
|
|
2019-07-05 17:25:05 +02:00
|
|
|
bool haveGVs() const { return RefAndFlags.getInt() & HaveGV; }
|
|
|
|
bool isReadOnly() const {
|
|
|
|
assert(isValidAccessSpecifier());
|
|
|
|
return RefAndFlags.getInt() & ReadOnly;
|
|
|
|
}
|
|
|
|
bool isWriteOnly() const {
|
|
|
|
assert(isValidAccessSpecifier());
|
|
|
|
return RefAndFlags.getInt() & WriteOnly;
|
|
|
|
}
|
|
|
|
unsigned getAccessSpecifier() const {
|
|
|
|
assert(isValidAccessSpecifier());
|
|
|
|
return RefAndFlags.getInt() & (ReadOnly | WriteOnly);
|
|
|
|
}
|
|
|
|
bool isValidAccessSpecifier() const {
|
|
|
|
unsigned BadAccessMask = ReadOnly | WriteOnly;
|
|
|
|
return (RefAndFlags.getInt() & BadAccessMask) != BadAccessMask;
|
|
|
|
}
|
|
|
|
void setReadOnly() {
|
|
|
|
// We expect ro/wo attribute to set only once during
|
|
|
|
// ValueInfo lifetime.
|
|
|
|
assert(getAccessSpecifier() == 0);
|
|
|
|
RefAndFlags.setInt(RefAndFlags.getInt() | ReadOnly);
|
|
|
|
}
|
|
|
|
void setWriteOnly() {
|
|
|
|
assert(getAccessSpecifier() == 0);
|
|
|
|
RefAndFlags.setInt(RefAndFlags.getInt() | WriteOnly);
|
|
|
|
}
|
2018-01-22 14:35:40 +01:00
|
|
|
|
|
|
|
const GlobalValueSummaryMapTy::value_type *getRef() const {
|
2018-11-16 08:08:00 +01:00
|
|
|
return RefAndFlags.getPointer();
|
2017-05-04 13:49:39 +02:00
|
|
|
}
|
2018-02-05 18:17:51 +01:00
|
|
|
|
|
|
|
bool isDSOLocal() const;
|
[ThinLTO] Auto-hide prevailing linkonce_odr only when all copies eligible
Summary:
We hit undefined references building with ThinLTO when one source file
contained explicit instantiations of a template method (weak_odr) but
there were also implicit instantiations in another file (linkonce_odr),
and the latter was the prevailing copy. In this case the symbol was
marked hidden when the prevailing linkonce_odr copy was promoted to
weak_odr. It led to unsats when the resulting shared library was linked
with other code that contained a reference (expecting to be resolved due
to the explicit instantiation).
Add a CanAutoHide flag to the GV summary to allow the thin link to
identify when all copies are eligible for auto-hiding (because they were
all originally linkonce_odr global unnamed addr), and only do the
auto-hide in that case.
Most of the changes here are due to plumbing the new flag through the
bitcode and llvm assembly, and resulting test changes. I augmented the
existing auto-hide test to check for this situation.
Reviewers: pcc
Subscribers: mehdi_amini, inglorion, eraman, dexonsmith, arphaman, dang, llvm-commits, steven_wu, wmi
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59709
llvm-svn: 360466
2019-05-10 22:08:24 +02:00
|
|
|
|
|
|
|
/// Checks if all copies are eligible for auto-hiding (have flag set).
|
|
|
|
bool canAutoHide() const;
|
2017-05-04 20:03:25 +02:00
|
|
|
};
|
|
|
|
|
2018-06-27 20:03:39 +02:00
|
|
|
inline raw_ostream &operator<<(raw_ostream &OS, const ValueInfo &VI) {
|
|
|
|
OS << VI.getGUID();
|
|
|
|
if (!VI.name().empty())
|
|
|
|
OS << " (" << VI.name() << ")";
|
|
|
|
return OS;
|
|
|
|
}
|
|
|
|
|
2018-02-19 16:14:50 +01:00
|
|
|
inline bool operator==(const ValueInfo &A, const ValueInfo &B) {
|
|
|
|
assert(A.getRef() && B.getRef() &&
|
2018-06-06 20:32:16 +02:00
|
|
|
"Need ValueInfo with non-null Ref for comparison");
|
2018-02-19 16:14:50 +01:00
|
|
|
return A.getRef() == B.getRef();
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool operator!=(const ValueInfo &A, const ValueInfo &B) {
|
|
|
|
assert(A.getRef() && B.getRef() &&
|
2018-06-06 20:32:16 +02:00
|
|
|
"Need ValueInfo with non-null Ref for comparison");
|
|
|
|
return A.getRef() != B.getRef();
|
2018-02-19 16:14:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline bool operator<(const ValueInfo &A, const ValueInfo &B) {
|
|
|
|
assert(A.getRef() && B.getRef() &&
|
|
|
|
"Need ValueInfo with non-null Ref to compare GUIDs");
|
|
|
|
return A.getGUID() < B.getGUID();
|
|
|
|
}
|
|
|
|
|
2017-05-04 20:03:25 +02:00
|
|
|
template <> struct DenseMapInfo<ValueInfo> {
|
|
|
|
static inline ValueInfo getEmptyKey() {
|
2018-01-22 14:35:40 +01:00
|
|
|
return ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-8);
|
2017-05-04 13:49:39 +02:00
|
|
|
}
|
2017-05-13 00:25:07 +02:00
|
|
|
|
2017-05-04 20:03:25 +02:00
|
|
|
static inline ValueInfo getTombstoneKey() {
|
2018-01-22 14:35:40 +01:00
|
|
|
return ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-16);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool isSpecialKey(ValueInfo V) {
|
|
|
|
return V == getTombstoneKey() || V == getEmptyKey();
|
2016-12-20 22:12:28 +01:00
|
|
|
}
|
2017-05-13 00:25:07 +02:00
|
|
|
|
2018-01-22 14:35:40 +01:00
|
|
|
static bool isEqual(ValueInfo L, ValueInfo R) {
|
2018-06-07 00:22:01 +02:00
|
|
|
// We are not supposed to mix ValueInfo(s) with different HaveGVs flag
|
2018-01-22 14:35:40 +01:00
|
|
|
// in a same container.
|
2018-06-07 00:22:01 +02:00
|
|
|
assert(isSpecialKey(L) || isSpecialKey(R) || (L.haveGVs() == R.haveGVs()));
|
2018-01-22 14:35:40 +01:00
|
|
|
return L.getRef() == R.getRef();
|
|
|
|
}
|
|
|
|
static unsigned getHashValue(ValueInfo I) { return (uintptr_t)I.getRef(); }
|
2016-12-20 22:12:28 +01:00
|
|
|
};
|
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Function and variable summary information to aid decisions and
|
2016-03-14 22:18:10 +01:00
|
|
|
/// implementation of importing.
|
|
|
|
class GlobalValueSummary {
|
|
|
|
public:
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Sububclass discriminator (for dyn_cast<> et al.)
|
2016-12-22 05:09:29 +01:00
|
|
|
enum SummaryKind : unsigned { AliasKind, FunctionKind, GlobalVarKind };
|
2016-03-14 22:18:10 +01:00
|
|
|
|
2017-01-05 15:32:16 +01:00
|
|
|
/// Group flags (Linkage, NotEligibleToImport, etc.) as a bitfield.
|
2016-04-24 05:18:18 +02:00
|
|
|
struct GVFlags {
|
2018-05-01 17:54:18 +02:00
|
|
|
/// The linkage type of the associated global value.
|
2016-04-24 05:18:18 +02:00
|
|
|
///
|
|
|
|
/// One use is to flag values that have local linkage types and need to
|
|
|
|
/// have module identifier appended before placing into the combined
|
|
|
|
/// index, to disambiguate from other values with the same name.
|
|
|
|
/// In the future this will be used to update and optimize linkage
|
|
|
|
/// types based on global summary-based analysis.
|
2016-04-24 16:25:37 +02:00
|
|
|
unsigned Linkage : 4;
|
2016-04-24 05:18:18 +02:00
|
|
|
|
2017-01-05 15:32:16 +01:00
|
|
|
/// Indicate if the global value cannot be imported (e.g. it cannot
|
|
|
|
/// be renamed or references something that can't be renamed).
|
|
|
|
unsigned NotEligibleToImport : 1;
|
2016-08-12 00:13:57 +02:00
|
|
|
|
2017-06-01 22:30:06 +02:00
|
|
|
/// In per-module summary, indicate that the global value must be considered
|
|
|
|
/// a live root for index-based liveness analysis. Used for special LLVM
|
|
|
|
/// values such as llvm.global_ctors that the linker does not know about.
|
|
|
|
///
|
|
|
|
/// In combined summary, indicate that the global value is live.
|
|
|
|
unsigned Live : 1;
|
2017-01-05 22:34:18 +01:00
|
|
|
|
2017-11-04 18:04:39 +01:00
|
|
|
/// Indicates that the linker resolved the symbol to a definition from
|
|
|
|
/// within the same linkage unit.
|
|
|
|
unsigned DSOLocal : 1;
|
|
|
|
|
[ThinLTO] Auto-hide prevailing linkonce_odr only when all copies eligible
Summary:
We hit undefined references building with ThinLTO when one source file
contained explicit instantiations of a template method (weak_odr) but
there were also implicit instantiations in another file (linkonce_odr),
and the latter was the prevailing copy. In this case the symbol was
marked hidden when the prevailing linkonce_odr copy was promoted to
weak_odr. It led to unsats when the resulting shared library was linked
with other code that contained a reference (expecting to be resolved due
to the explicit instantiation).
Add a CanAutoHide flag to the GV summary to allow the thin link to
identify when all copies are eligible for auto-hiding (because they were
all originally linkonce_odr global unnamed addr), and only do the
auto-hide in that case.
Most of the changes here are due to plumbing the new flag through the
bitcode and llvm assembly, and resulting test changes. I augmented the
existing auto-hide test to check for this situation.
Reviewers: pcc
Subscribers: mehdi_amini, inglorion, eraman, dexonsmith, arphaman, dang, llvm-commits, steven_wu, wmi
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59709
llvm-svn: 360466
2019-05-10 22:08:24 +02:00
|
|
|
/// In the per-module summary, indicates that the global value is
|
|
|
|
/// linkonce_odr and global unnamed addr (so eligible for auto-hiding
|
|
|
|
/// via hidden visibility). In the combined summary, indicates that the
|
|
|
|
/// prevailing linkonce_odr copy can be auto-hidden via hidden visibility
|
|
|
|
/// when it is upgraded to weak_odr in the backend. This is legal when
|
|
|
|
/// all copies are eligible for auto-hiding (i.e. all copies were
|
|
|
|
/// linkonce_odr global unnamed addr. If any copy is not (e.g. it was
|
|
|
|
/// originally weak_odr, we cannot auto-hide the prevailing copy as it
|
|
|
|
/// means the symbol was externally visible.
|
|
|
|
unsigned CanAutoHide : 1;
|
|
|
|
|
2016-04-24 05:18:18 +02:00
|
|
|
/// Convenience Constructors
|
2017-01-05 15:32:16 +01:00
|
|
|
explicit GVFlags(GlobalValue::LinkageTypes Linkage,
|
[ThinLTO] Auto-hide prevailing linkonce_odr only when all copies eligible
Summary:
We hit undefined references building with ThinLTO when one source file
contained explicit instantiations of a template method (weak_odr) but
there were also implicit instantiations in another file (linkonce_odr),
and the latter was the prevailing copy. In this case the symbol was
marked hidden when the prevailing linkonce_odr copy was promoted to
weak_odr. It led to unsats when the resulting shared library was linked
with other code that contained a reference (expecting to be resolved due
to the explicit instantiation).
Add a CanAutoHide flag to the GV summary to allow the thin link to
identify when all copies are eligible for auto-hiding (because they were
all originally linkonce_odr global unnamed addr), and only do the
auto-hide in that case.
Most of the changes here are due to plumbing the new flag through the
bitcode and llvm assembly, and resulting test changes. I augmented the
existing auto-hide test to check for this situation.
Reviewers: pcc
Subscribers: mehdi_amini, inglorion, eraman, dexonsmith, arphaman, dang, llvm-commits, steven_wu, wmi
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59709
llvm-svn: 360466
2019-05-10 22:08:24 +02:00
|
|
|
bool NotEligibleToImport, bool Live, bool IsLocal,
|
|
|
|
bool CanAutoHide)
|
2017-01-05 22:34:18 +01:00
|
|
|
: Linkage(Linkage), NotEligibleToImport(NotEligibleToImport),
|
[ThinLTO] Auto-hide prevailing linkonce_odr only when all copies eligible
Summary:
We hit undefined references building with ThinLTO when one source file
contained explicit instantiations of a template method (weak_odr) but
there were also implicit instantiations in another file (linkonce_odr),
and the latter was the prevailing copy. In this case the symbol was
marked hidden when the prevailing linkonce_odr copy was promoted to
weak_odr. It led to unsats when the resulting shared library was linked
with other code that contained a reference (expecting to be resolved due
to the explicit instantiation).
Add a CanAutoHide flag to the GV summary to allow the thin link to
identify when all copies are eligible for auto-hiding (because they were
all originally linkonce_odr global unnamed addr), and only do the
auto-hide in that case.
Most of the changes here are due to plumbing the new flag through the
bitcode and llvm assembly, and resulting test changes. I augmented the
existing auto-hide test to check for this situation.
Reviewers: pcc
Subscribers: mehdi_amini, inglorion, eraman, dexonsmith, arphaman, dang, llvm-commits, steven_wu, wmi
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59709
llvm-svn: 360466
2019-05-10 22:08:24 +02:00
|
|
|
Live(Live), DSOLocal(IsLocal), CanAutoHide(CanAutoHide) {}
|
2016-04-24 05:18:18 +02:00
|
|
|
};
|
|
|
|
|
2016-03-14 22:18:10 +01:00
|
|
|
private:
|
|
|
|
/// Kind of summary for use in dyn_cast<> et al.
|
|
|
|
SummaryKind Kind;
|
|
|
|
|
2016-12-22 05:09:29 +01:00
|
|
|
GVFlags Flags;
|
|
|
|
|
2016-04-24 01:38:17 +02:00
|
|
|
/// This is the hash of the name of the symbol in the original file. It is
|
|
|
|
/// identical to the GUID for global symbols, but differs for local since the
|
|
|
|
/// GUID includes the module level id in the hash.
|
2017-05-13 00:25:07 +02:00
|
|
|
GlobalValue::GUID OriginalName = 0;
|
2016-04-24 01:38:17 +02:00
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Path of module IR containing value's definition, used to locate
|
2016-03-14 22:18:10 +01:00
|
|
|
/// module during importing.
|
|
|
|
///
|
|
|
|
/// This is only used during parsing of the combined index, or when
|
2016-03-15 01:04:37 +01:00
|
|
|
/// parsing the per-module index for creation of the combined summary index,
|
2016-03-14 22:18:10 +01:00
|
|
|
/// not during writing of the per-module index which doesn't contain a
|
|
|
|
/// module path string table.
|
|
|
|
StringRef ModulePath;
|
|
|
|
|
2016-04-11 15:58:45 +02:00
|
|
|
/// List of values referenced by this global value's definition
|
2016-03-14 22:18:10 +01:00
|
|
|
/// (either by the initializer of a global variable, or referenced
|
|
|
|
/// from within a function). This does not include functions called, which
|
|
|
|
/// are listed in the derived FunctionSummary object.
|
2016-04-11 15:58:45 +02:00
|
|
|
std::vector<ValueInfo> RefEdgeList;
|
2016-03-14 22:18:10 +01:00
|
|
|
|
|
|
|
protected:
|
2016-12-20 22:12:28 +01:00
|
|
|
GlobalValueSummary(SummaryKind K, GVFlags Flags, std::vector<ValueInfo> Refs)
|
2017-09-13 19:10:24 +02:00
|
|
|
: Kind(K), Flags(Flags), RefEdgeList(std::move(Refs)) {
|
|
|
|
assert((K != AliasKind || Refs.empty()) &&
|
|
|
|
"Expect no references for AliasSummary");
|
|
|
|
}
|
2016-03-14 22:18:10 +01:00
|
|
|
|
|
|
|
public:
|
|
|
|
virtual ~GlobalValueSummary() = default;
|
|
|
|
|
2016-04-24 01:38:17 +02:00
|
|
|
/// Returns the hash of the original name, it is identical to the GUID for
|
|
|
|
/// externally visible symbols, but not for local ones.
|
2018-05-31 17:15:33 +02:00
|
|
|
GlobalValue::GUID getOriginalName() const { return OriginalName; }
|
2016-04-24 01:38:17 +02:00
|
|
|
|
|
|
|
/// Initialize the original name hash in this summary.
|
|
|
|
void setOriginalName(GlobalValue::GUID Name) { OriginalName = Name; }
|
|
|
|
|
2016-03-14 22:18:10 +01:00
|
|
|
/// Which kind of summary subclass this is.
|
|
|
|
SummaryKind getSummaryKind() const { return Kind; }
|
|
|
|
|
|
|
|
/// Set the path to the module containing this function, for use in
|
|
|
|
/// the combined index.
|
|
|
|
void setModulePath(StringRef ModPath) { ModulePath = ModPath; }
|
|
|
|
|
|
|
|
/// Get the path to the module containing this function.
|
|
|
|
StringRef modulePath() const { return ModulePath; }
|
|
|
|
|
2016-04-24 05:18:18 +02:00
|
|
|
/// Get the flags for this GlobalValue (see \p struct GVFlags).
|
2018-05-16 16:56:02 +02:00
|
|
|
GVFlags flags() const { return Flags; }
|
2016-04-24 05:18:18 +02:00
|
|
|
|
2016-03-14 22:18:10 +01:00
|
|
|
/// Return linkage type recorded for this global value.
|
2016-04-24 16:25:37 +02:00
|
|
|
GlobalValue::LinkageTypes linkage() const {
|
|
|
|
return static_cast<GlobalValue::LinkageTypes>(Flags.Linkage);
|
|
|
|
}
|
2016-03-14 22:18:10 +01:00
|
|
|
|
2016-05-24 19:24:25 +02:00
|
|
|
/// Sets the linkage to the value determined by global summary-based
|
|
|
|
/// optimization. Will be applied in the ThinLTO backends.
|
|
|
|
void setLinkage(GlobalValue::LinkageTypes Linkage) {
|
|
|
|
Flags.Linkage = Linkage;
|
|
|
|
}
|
|
|
|
|
2017-01-05 15:32:16 +01:00
|
|
|
/// Return true if this global value can't be imported.
|
|
|
|
bool notEligibleToImport() const { return Flags.NotEligibleToImport; }
|
2016-04-24 07:31:43 +02:00
|
|
|
|
2018-01-25 12:45:02 +01:00
|
|
|
bool isLive() const { return Flags.Live; }
|
|
|
|
|
2017-06-01 22:30:06 +02:00
|
|
|
void setLive(bool Live) { Flags.Live = Live; }
|
2017-01-05 22:34:18 +01:00
|
|
|
|
2017-11-04 18:04:39 +01:00
|
|
|
void setDSOLocal(bool Local) { Flags.DSOLocal = Local; }
|
|
|
|
|
|
|
|
bool isDSOLocal() const { return Flags.DSOLocal; }
|
|
|
|
|
[ThinLTO] Auto-hide prevailing linkonce_odr only when all copies eligible
Summary:
We hit undefined references building with ThinLTO when one source file
contained explicit instantiations of a template method (weak_odr) but
there were also implicit instantiations in another file (linkonce_odr),
and the latter was the prevailing copy. In this case the symbol was
marked hidden when the prevailing linkonce_odr copy was promoted to
weak_odr. It led to unsats when the resulting shared library was linked
with other code that contained a reference (expecting to be resolved due
to the explicit instantiation).
Add a CanAutoHide flag to the GV summary to allow the thin link to
identify when all copies are eligible for auto-hiding (because they were
all originally linkonce_odr global unnamed addr), and only do the
auto-hide in that case.
Most of the changes here are due to plumbing the new flag through the
bitcode and llvm assembly, and resulting test changes. I augmented the
existing auto-hide test to check for this situation.
Reviewers: pcc
Subscribers: mehdi_amini, inglorion, eraman, dexonsmith, arphaman, dang, llvm-commits, steven_wu, wmi
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59709
llvm-svn: 360466
2019-05-10 22:08:24 +02:00
|
|
|
void setCanAutoHide(bool CanAutoHide) { Flags.CanAutoHide = CanAutoHide; }
|
|
|
|
|
|
|
|
bool canAutoHide() const { return Flags.CanAutoHide; }
|
|
|
|
|
2017-01-05 15:32:16 +01:00
|
|
|
/// Flag that this global value cannot be imported.
|
|
|
|
void setNotEligibleToImport() { Flags.NotEligibleToImport = true; }
|
2016-11-14 17:40:19 +01:00
|
|
|
|
2016-04-11 15:58:45 +02:00
|
|
|
/// Return the list of values referenced by this global value definition.
|
2016-12-20 22:12:28 +01:00
|
|
|
ArrayRef<ValueInfo> refs() const { return RefEdgeList; }
|
2017-06-01 22:30:06 +02:00
|
|
|
|
2017-09-14 07:02:59 +02:00
|
|
|
/// If this is an alias summary, returns the summary of the aliased object (a
|
|
|
|
/// global variable or function), otherwise returns itself.
|
|
|
|
GlobalValueSummary *getBaseObject();
|
2017-12-16 01:18:12 +01:00
|
|
|
const GlobalValueSummary *getBaseObject() const;
|
2017-09-14 07:02:59 +02:00
|
|
|
|
2017-06-01 22:30:06 +02:00
|
|
|
friend class ModuleSummaryIndex;
|
2016-03-14 22:18:10 +01:00
|
|
|
};
|
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Alias summary information.
|
2016-04-16 08:56:44 +02:00
|
|
|
class AliasSummary : public GlobalValueSummary {
|
[ThinLTO] Restructure AliasSummary to contain ValueInfo of Aliasee
Summary:
The AliasSummary previously contained the AliaseeGUID, which was only
populated when reading the summary from bitcode. This patch changes it
to instead hold the ValueInfo of the aliasee, and always populates it.
This enables more efficient access to the ValueInfo (specifically in the
recent patch r352438 which needed to perform an index hash table lookup
using the aliasee GUID).
As noted in the comments in AliasSummary, we no longer technically need
to keep a pointer to the corresponding aliasee summary, since it could
be obtained by walking the list of summaries on the ValueInfo looking
for the summary in the same module. However, I am concerned that this
would be inefficient when walking through the index during the thin
link for various analyses. That can be reevaluated in the future.
By always populating this new field, we can remove the guard and special
handling for a 0 aliasee GUID when dumping the dot graph of the summary.
An additional improvement in this patch is when reading the summaries
from LLVM assembly we now set the AliaseeSummary field to the aliasee
summary in that same module, which makes it consistent with the behavior
when reading the summary from bitcode.
Reviewers: pcc, mehdi_amini
Subscribers: inglorion, eraman, steven_wu, dexonsmith, arphaman, llvm-commits
Differential Revision: https://reviews.llvm.org/D57470
llvm-svn: 356268
2019-03-15 16:11:38 +01:00
|
|
|
ValueInfo AliaseeValueInfo;
|
|
|
|
|
|
|
|
/// This is the Aliasee in the same module as alias (could get from VI, trades
|
|
|
|
/// memory for time). Note that this pointer may be null (and the value info
|
|
|
|
/// empty) when we have a distributed index where the alias is being imported
|
|
|
|
/// (as a copy of the aliasee), but the aliasee is not.
|
2016-04-16 08:56:44 +02:00
|
|
|
GlobalValueSummary *AliaseeSummary;
|
|
|
|
|
|
|
|
public:
|
2017-09-13 19:10:24 +02:00
|
|
|
AliasSummary(GVFlags Flags)
|
2017-12-16 01:18:12 +01:00
|
|
|
: GlobalValueSummary(AliasKind, Flags, ArrayRef<ValueInfo>{}),
|
[ThinLTO] Restructure AliasSummary to contain ValueInfo of Aliasee
Summary:
The AliasSummary previously contained the AliaseeGUID, which was only
populated when reading the summary from bitcode. This patch changes it
to instead hold the ValueInfo of the aliasee, and always populates it.
This enables more efficient access to the ValueInfo (specifically in the
recent patch r352438 which needed to perform an index hash table lookup
using the aliasee GUID).
As noted in the comments in AliasSummary, we no longer technically need
to keep a pointer to the corresponding aliasee summary, since it could
be obtained by walking the list of summaries on the ValueInfo looking
for the summary in the same module. However, I am concerned that this
would be inefficient when walking through the index during the thin
link for various analyses. That can be reevaluated in the future.
By always populating this new field, we can remove the guard and special
handling for a 0 aliasee GUID when dumping the dot graph of the summary.
An additional improvement in this patch is when reading the summaries
from LLVM assembly we now set the AliaseeSummary field to the aliasee
summary in that same module, which makes it consistent with the behavior
when reading the summary from bitcode.
Reviewers: pcc, mehdi_amini
Subscribers: inglorion, eraman, steven_wu, dexonsmith, arphaman, llvm-commits
Differential Revision: https://reviews.llvm.org/D57470
llvm-svn: 356268
2019-03-15 16:11:38 +01:00
|
|
|
AliaseeSummary(nullptr) {}
|
2016-04-16 08:56:44 +02:00
|
|
|
|
|
|
|
/// Check if this is an alias summary.
|
|
|
|
static bool classof(const GlobalValueSummary *GVS) {
|
|
|
|
return GVS->getSummaryKind() == AliasKind;
|
|
|
|
}
|
|
|
|
|
[ThinLTO] Restructure AliasSummary to contain ValueInfo of Aliasee
Summary:
The AliasSummary previously contained the AliaseeGUID, which was only
populated when reading the summary from bitcode. This patch changes it
to instead hold the ValueInfo of the aliasee, and always populates it.
This enables more efficient access to the ValueInfo (specifically in the
recent patch r352438 which needed to perform an index hash table lookup
using the aliasee GUID).
As noted in the comments in AliasSummary, we no longer technically need
to keep a pointer to the corresponding aliasee summary, since it could
be obtained by walking the list of summaries on the ValueInfo looking
for the summary in the same module. However, I am concerned that this
would be inefficient when walking through the index during the thin
link for various analyses. That can be reevaluated in the future.
By always populating this new field, we can remove the guard and special
handling for a 0 aliasee GUID when dumping the dot graph of the summary.
An additional improvement in this patch is when reading the summaries
from LLVM assembly we now set the AliaseeSummary field to the aliasee
summary in that same module, which makes it consistent with the behavior
when reading the summary from bitcode.
Reviewers: pcc, mehdi_amini
Subscribers: inglorion, eraman, steven_wu, dexonsmith, arphaman, llvm-commits
Differential Revision: https://reviews.llvm.org/D57470
llvm-svn: 356268
2019-03-15 16:11:38 +01:00
|
|
|
void setAliasee(ValueInfo &AliaseeVI, GlobalValueSummary *Aliasee) {
|
|
|
|
AliaseeValueInfo = AliaseeVI;
|
|
|
|
AliaseeSummary = Aliasee;
|
|
|
|
}
|
2016-04-16 08:56:44 +02:00
|
|
|
|
[ThinLTO] Restructure AliasSummary to contain ValueInfo of Aliasee
Summary:
The AliasSummary previously contained the AliaseeGUID, which was only
populated when reading the summary from bitcode. This patch changes it
to instead hold the ValueInfo of the aliasee, and always populates it.
This enables more efficient access to the ValueInfo (specifically in the
recent patch r352438 which needed to perform an index hash table lookup
using the aliasee GUID).
As noted in the comments in AliasSummary, we no longer technically need
to keep a pointer to the corresponding aliasee summary, since it could
be obtained by walking the list of summaries on the ValueInfo looking
for the summary in the same module. However, I am concerned that this
would be inefficient when walking through the index during the thin
link for various analyses. That can be reevaluated in the future.
By always populating this new field, we can remove the guard and special
handling for a 0 aliasee GUID when dumping the dot graph of the summary.
An additional improvement in this patch is when reading the summaries
from LLVM assembly we now set the AliaseeSummary field to the aliasee
summary in that same module, which makes it consistent with the behavior
when reading the summary from bitcode.
Reviewers: pcc, mehdi_amini
Subscribers: inglorion, eraman, steven_wu, dexonsmith, arphaman, llvm-commits
Differential Revision: https://reviews.llvm.org/D57470
llvm-svn: 356268
2019-03-15 16:11:38 +01:00
|
|
|
bool hasAliasee() const {
|
|
|
|
assert(!!AliaseeSummary == (AliaseeValueInfo &&
|
|
|
|
!AliaseeValueInfo.getSummaryList().empty()) &&
|
|
|
|
"Expect to have both aliasee summary and summary list or neither");
|
|
|
|
return !!AliaseeSummary;
|
|
|
|
}
|
2018-06-26 15:56:49 +02:00
|
|
|
|
2016-04-16 08:56:44 +02:00
|
|
|
const GlobalValueSummary &getAliasee() const {
|
2017-03-27 07:47:03 +02:00
|
|
|
assert(AliaseeSummary && "Unexpected missing aliasee summary");
|
|
|
|
return *AliaseeSummary;
|
2016-04-16 08:56:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
GlobalValueSummary &getAliasee() {
|
2017-03-27 07:47:03 +02:00
|
|
|
return const_cast<GlobalValueSummary &>(
|
|
|
|
static_cast<const AliasSummary *>(this)->getAliasee());
|
2016-04-16 08:56:44 +02:00
|
|
|
}
|
[ThinLTO] Restructure AliasSummary to contain ValueInfo of Aliasee
Summary:
The AliasSummary previously contained the AliaseeGUID, which was only
populated when reading the summary from bitcode. This patch changes it
to instead hold the ValueInfo of the aliasee, and always populates it.
This enables more efficient access to the ValueInfo (specifically in the
recent patch r352438 which needed to perform an index hash table lookup
using the aliasee GUID).
As noted in the comments in AliasSummary, we no longer technically need
to keep a pointer to the corresponding aliasee summary, since it could
be obtained by walking the list of summaries on the ValueInfo looking
for the summary in the same module. However, I am concerned that this
would be inefficient when walking through the index during the thin
link for various analyses. That can be reevaluated in the future.
By always populating this new field, we can remove the guard and special
handling for a 0 aliasee GUID when dumping the dot graph of the summary.
An additional improvement in this patch is when reading the summaries
from LLVM assembly we now set the AliaseeSummary field to the aliasee
summary in that same module, which makes it consistent with the behavior
when reading the summary from bitcode.
Reviewers: pcc, mehdi_amini
Subscribers: inglorion, eraman, steven_wu, dexonsmith, arphaman, llvm-commits
Differential Revision: https://reviews.llvm.org/D57470
llvm-svn: 356268
2019-03-15 16:11:38 +01:00
|
|
|
ValueInfo getAliaseeVI() const {
|
|
|
|
assert(AliaseeValueInfo && "Unexpected missing aliasee");
|
|
|
|
return AliaseeValueInfo;
|
|
|
|
}
|
|
|
|
GlobalValue::GUID getAliaseeGUID() const {
|
|
|
|
assert(AliaseeValueInfo && "Unexpected missing aliasee");
|
|
|
|
return AliaseeValueInfo.getGUID();
|
2017-12-16 01:18:12 +01:00
|
|
|
}
|
2016-04-16 08:56:44 +02:00
|
|
|
};
|
|
|
|
|
2017-12-16 01:18:12 +01:00
|
|
|
const inline GlobalValueSummary *GlobalValueSummary::getBaseObject() const {
|
|
|
|
if (auto *AS = dyn_cast<AliasSummary>(this))
|
|
|
|
return &AS->getAliasee();
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2017-09-14 07:02:59 +02:00
|
|
|
inline GlobalValueSummary *GlobalValueSummary::getBaseObject() {
|
|
|
|
if (auto *AS = dyn_cast<AliasSummary>(this))
|
|
|
|
return &AS->getAliasee();
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Function summary information to aid decisions and implementation of
|
2016-03-14 22:18:10 +01:00
|
|
|
/// importing.
|
|
|
|
class FunctionSummary : public GlobalValueSummary {
|
|
|
|
public:
|
2016-04-11 15:58:45 +02:00
|
|
|
/// <CalleeValueInfo, CalleeInfo> call edge pair.
|
2017-05-13 00:25:07 +02:00
|
|
|
using EdgeTy = std::pair<ValueInfo, CalleeInfo>;
|
2016-03-14 22:18:10 +01:00
|
|
|
|
2018-03-31 02:18:08 +02:00
|
|
|
/// Types for -force-summary-edges-cold debugging option.
|
|
|
|
enum ForceSummaryHotnessType : unsigned {
|
|
|
|
FSHT_None,
|
|
|
|
FSHT_AllNonCritical,
|
|
|
|
FSHT_All
|
|
|
|
};
|
|
|
|
|
2017-02-10 23:29:38 +01:00
|
|
|
/// An "identifier" for a virtual function. This contains the type identifier
|
|
|
|
/// represented as a GUID and the offset from the address point to the virtual
|
2017-02-11 04:19:22 +01:00
|
|
|
/// function pointer, where "address point" is as defined in the Itanium ABI:
|
2017-09-12 02:19:11 +02:00
|
|
|
/// https://itanium-cxx-abi.github.io/cxx-abi/abi.html#vtable-general
|
2017-02-10 23:29:38 +01:00
|
|
|
struct VFuncId {
|
|
|
|
GlobalValue::GUID GUID;
|
|
|
|
uint64_t Offset;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// A specification for a virtual function call with all constant integer
|
|
|
|
/// arguments. This is used to perform virtual constant propagation on the
|
|
|
|
/// summary.
|
|
|
|
struct ConstVCall {
|
|
|
|
VFuncId VFunc;
|
|
|
|
std::vector<uint64_t> Args;
|
|
|
|
};
|
|
|
|
|
2018-05-26 04:34:13 +02:00
|
|
|
/// All type identifier related information. Because these fields are
|
|
|
|
/// relatively uncommon we only allocate space for them if necessary.
|
|
|
|
struct TypeIdInfo {
|
|
|
|
/// List of type identifiers used by this function in llvm.type.test
|
|
|
|
/// intrinsics referenced by something other than an llvm.assume intrinsic,
|
|
|
|
/// represented as GUIDs.
|
|
|
|
std::vector<GlobalValue::GUID> TypeTests;
|
|
|
|
|
|
|
|
/// List of virtual calls made by this function using (respectively)
|
|
|
|
/// llvm.assume(llvm.type.test) or llvm.type.checked.load intrinsics that do
|
|
|
|
/// not have all constant integer arguments.
|
|
|
|
std::vector<VFuncId> TypeTestAssumeVCalls, TypeCheckedLoadVCalls;
|
|
|
|
|
|
|
|
/// List of virtual calls made by this function using (respectively)
|
|
|
|
/// llvm.assume(llvm.type.test) or llvm.type.checked.load intrinsics with
|
|
|
|
/// all constant integer arguments.
|
|
|
|
std::vector<ConstVCall> TypeTestAssumeConstVCalls,
|
|
|
|
TypeCheckedLoadConstVCalls;
|
|
|
|
};
|
|
|
|
|
2018-11-06 20:41:35 +01:00
|
|
|
/// Flags specific to function summaries.
|
2017-08-04 18:00:58 +02:00
|
|
|
struct FFlags {
|
2018-11-06 20:41:35 +01:00
|
|
|
// Function attribute flags. Used to track if a function accesses memory,
|
|
|
|
// recurses or aliases.
|
2017-08-04 18:00:58 +02:00
|
|
|
unsigned ReadNone : 1;
|
|
|
|
unsigned ReadOnly : 1;
|
|
|
|
unsigned NoRecurse : 1;
|
|
|
|
unsigned ReturnDoesNotAlias : 1;
|
2018-11-06 20:41:35 +01:00
|
|
|
|
|
|
|
// Indicate if the global value cannot be inlined.
|
|
|
|
unsigned NoInline : 1;
|
2019-11-09 00:50:55 +01:00
|
|
|
// Indicate if function should be always inlined.
|
|
|
|
unsigned AlwaysInline : 1;
|
2017-08-04 18:00:58 +02:00
|
|
|
};
|
|
|
|
|
2018-02-19 16:14:50 +01:00
|
|
|
/// Create an empty FunctionSummary (with specified call edges).
|
|
|
|
/// Used to represent external nodes and the dummy root node.
|
|
|
|
static FunctionSummary
|
|
|
|
makeDummyFunctionSummary(std::vector<FunctionSummary::EdgeTy> Edges) {
|
|
|
|
return FunctionSummary(
|
|
|
|
FunctionSummary::GVFlags(
|
|
|
|
GlobalValue::LinkageTypes::AvailableExternallyLinkage,
|
[ThinLTO] Auto-hide prevailing linkonce_odr only when all copies eligible
Summary:
We hit undefined references building with ThinLTO when one source file
contained explicit instantiations of a template method (weak_odr) but
there were also implicit instantiations in another file (linkonce_odr),
and the latter was the prevailing copy. In this case the symbol was
marked hidden when the prevailing linkonce_odr copy was promoted to
weak_odr. It led to unsats when the resulting shared library was linked
with other code that contained a reference (expecting to be resolved due
to the explicit instantiation).
Add a CanAutoHide flag to the GV summary to allow the thin link to
identify when all copies are eligible for auto-hiding (because they were
all originally linkonce_odr global unnamed addr), and only do the
auto-hide in that case.
Most of the changes here are due to plumbing the new flag through the
bitcode and llvm assembly, and resulting test changes. I augmented the
existing auto-hide test to check for this situation.
Reviewers: pcc
Subscribers: mehdi_amini, inglorion, eraman, dexonsmith, arphaman, dang, llvm-commits, steven_wu, wmi
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59709
llvm-svn: 360466
2019-05-10 22:08:24 +02:00
|
|
|
/*NotEligibleToImport=*/true, /*Live=*/true, /*IsLocal=*/false,
|
|
|
|
/*CanAutoHide=*/false),
|
2018-12-13 20:54:27 +01:00
|
|
|
/*InsCount=*/0, FunctionSummary::FFlags{}, /*EntryCount=*/0,
|
|
|
|
std::vector<ValueInfo>(), std::move(Edges),
|
|
|
|
std::vector<GlobalValue::GUID>(),
|
2018-02-19 16:14:50 +01:00
|
|
|
std::vector<FunctionSummary::VFuncId>(),
|
|
|
|
std::vector<FunctionSummary::VFuncId>(),
|
|
|
|
std::vector<FunctionSummary::ConstVCall>(),
|
|
|
|
std::vector<FunctionSummary::ConstVCall>());
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A dummy node to reference external functions that aren't in the index
|
|
|
|
static FunctionSummary ExternalNode;
|
|
|
|
|
2016-03-14 22:18:10 +01:00
|
|
|
private:
|
|
|
|
/// Number of instructions (ignoring debug instructions, e.g.) computed
|
2016-03-15 01:04:37 +01:00
|
|
|
/// during the initial compile step when the summary index is first built.
|
2016-03-14 22:18:10 +01:00
|
|
|
unsigned InstCount;
|
|
|
|
|
2018-11-06 20:41:35 +01:00
|
|
|
/// Function summary specific flags.
|
2017-08-04 18:00:58 +02:00
|
|
|
FFlags FunFlags;
|
|
|
|
|
2018-12-13 20:54:27 +01:00
|
|
|
/// The synthesized entry count of the function.
|
|
|
|
/// This is only populated during ThinLink phase and remains unused while
|
|
|
|
/// generating per-module summaries.
|
|
|
|
uint64_t EntryCount = 0;
|
|
|
|
|
2016-04-11 15:58:45 +02:00
|
|
|
/// List of <CalleeValueInfo, CalleeInfo> call edge pairs from this function.
|
2016-03-14 22:18:10 +01:00
|
|
|
std::vector<EdgeTy> CallGraphEdgeList;
|
|
|
|
|
2017-02-11 04:19:22 +01:00
|
|
|
std::unique_ptr<TypeIdInfo> TIdInfo;
|
2016-12-22 00:03:45 +01:00
|
|
|
|
2016-03-14 22:18:10 +01:00
|
|
|
public:
|
2017-08-04 18:00:58 +02:00
|
|
|
FunctionSummary(GVFlags Flags, unsigned NumInsts, FFlags FunFlags,
|
2018-12-13 20:54:27 +01:00
|
|
|
uint64_t EntryCount, std::vector<ValueInfo> Refs,
|
|
|
|
std::vector<EdgeTy> CGEdges,
|
2017-02-10 23:29:38 +01:00
|
|
|
std::vector<GlobalValue::GUID> TypeTests,
|
|
|
|
std::vector<VFuncId> TypeTestAssumeVCalls,
|
|
|
|
std::vector<VFuncId> TypeCheckedLoadVCalls,
|
|
|
|
std::vector<ConstVCall> TypeTestAssumeConstVCalls,
|
|
|
|
std::vector<ConstVCall> TypeCheckedLoadConstVCalls)
|
2016-12-20 22:12:28 +01:00
|
|
|
: GlobalValueSummary(FunctionKind, Flags, std::move(Refs)),
|
2018-12-13 20:54:27 +01:00
|
|
|
InstCount(NumInsts), FunFlags(FunFlags), EntryCount(EntryCount),
|
2017-08-04 18:00:58 +02:00
|
|
|
CallGraphEdgeList(std::move(CGEdges)) {
|
2017-02-11 04:19:22 +01:00
|
|
|
if (!TypeTests.empty() || !TypeTestAssumeVCalls.empty() ||
|
|
|
|
!TypeCheckedLoadVCalls.empty() || !TypeTestAssumeConstVCalls.empty() ||
|
|
|
|
!TypeCheckedLoadConstVCalls.empty())
|
2019-08-15 17:54:37 +02:00
|
|
|
TIdInfo = std::make_unique<TypeIdInfo>(TypeIdInfo{
|
2017-02-11 04:19:22 +01:00
|
|
|
std::move(TypeTests), std::move(TypeTestAssumeVCalls),
|
|
|
|
std::move(TypeCheckedLoadVCalls),
|
|
|
|
std::move(TypeTestAssumeConstVCalls),
|
|
|
|
std::move(TypeCheckedLoadConstVCalls)});
|
|
|
|
}
|
2019-07-05 17:25:05 +02:00
|
|
|
// Gets the number of readonly and writeonly refs in RefEdgeList
|
|
|
|
std::pair<unsigned, unsigned> specialRefCounts() const;
|
2016-03-14 22:18:10 +01:00
|
|
|
|
|
|
|
/// Check if this is a function summary.
|
|
|
|
static bool classof(const GlobalValueSummary *GVS) {
|
|
|
|
return GVS->getSummaryKind() == FunctionKind;
|
|
|
|
}
|
|
|
|
|
2018-11-06 20:41:35 +01:00
|
|
|
/// Get function summary flags.
|
2018-05-16 16:56:02 +02:00
|
|
|
FFlags fflags() const { return FunFlags; }
|
2017-08-04 18:00:58 +02:00
|
|
|
|
2016-03-14 22:18:10 +01:00
|
|
|
/// Get the instruction count recorded for this function.
|
|
|
|
unsigned instCount() const { return InstCount; }
|
|
|
|
|
2018-12-13 20:54:27 +01:00
|
|
|
/// Get the synthetic entry count for this function.
|
|
|
|
uint64_t entryCount() const { return EntryCount; }
|
|
|
|
|
|
|
|
/// Set the synthetic entry count for this function.
|
|
|
|
void setEntryCount(uint64_t EC) { EntryCount = EC; }
|
|
|
|
|
2016-04-11 15:58:45 +02:00
|
|
|
/// Return the list of <CalleeValueInfo, CalleeInfo> pairs.
|
2016-12-20 22:12:28 +01:00
|
|
|
ArrayRef<EdgeTy> calls() const { return CallGraphEdgeList; }
|
2016-12-22 00:03:45 +01:00
|
|
|
|
2019-08-02 15:10:52 +02:00
|
|
|
void addCall(EdgeTy E) { CallGraphEdgeList.push_back(E); }
|
|
|
|
|
2017-02-10 23:29:38 +01:00
|
|
|
/// Returns the list of type identifiers used by this function in
|
|
|
|
/// llvm.type.test intrinsics other than by an llvm.assume intrinsic,
|
|
|
|
/// represented as GUIDs.
|
2017-02-11 04:19:22 +01:00
|
|
|
ArrayRef<GlobalValue::GUID> type_tests() const {
|
|
|
|
if (TIdInfo)
|
|
|
|
return TIdInfo->TypeTests;
|
|
|
|
return {};
|
|
|
|
}
|
2017-02-10 23:29:38 +01:00
|
|
|
|
|
|
|
/// Returns the list of virtual calls made by this function using
|
|
|
|
/// llvm.assume(llvm.type.test) intrinsics that do not have all constant
|
|
|
|
/// integer arguments.
|
|
|
|
ArrayRef<VFuncId> type_test_assume_vcalls() const {
|
2017-02-11 04:19:22 +01:00
|
|
|
if (TIdInfo)
|
|
|
|
return TIdInfo->TypeTestAssumeVCalls;
|
|
|
|
return {};
|
2017-02-10 23:29:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the list of virtual calls made by this function using
|
|
|
|
/// llvm.type.checked.load intrinsics that do not have all constant integer
|
|
|
|
/// arguments.
|
|
|
|
ArrayRef<VFuncId> type_checked_load_vcalls() const {
|
2017-02-11 04:19:22 +01:00
|
|
|
if (TIdInfo)
|
|
|
|
return TIdInfo->TypeCheckedLoadVCalls;
|
|
|
|
return {};
|
2017-02-10 23:29:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the list of virtual calls made by this function using
|
|
|
|
/// llvm.assume(llvm.type.test) intrinsics with all constant integer
|
|
|
|
/// arguments.
|
|
|
|
ArrayRef<ConstVCall> type_test_assume_const_vcalls() const {
|
2017-02-11 04:19:22 +01:00
|
|
|
if (TIdInfo)
|
|
|
|
return TIdInfo->TypeTestAssumeConstVCalls;
|
|
|
|
return {};
|
2017-02-10 23:29:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the list of virtual calls made by this function using
|
|
|
|
/// llvm.type.checked.load intrinsics with all constant integer arguments.
|
|
|
|
ArrayRef<ConstVCall> type_checked_load_const_vcalls() const {
|
2017-02-11 04:19:22 +01:00
|
|
|
if (TIdInfo)
|
|
|
|
return TIdInfo->TypeCheckedLoadConstVCalls;
|
|
|
|
return {};
|
2017-02-10 23:29:38 +01:00
|
|
|
}
|
2017-03-04 02:23:30 +01:00
|
|
|
|
|
|
|
/// Add a type test to the summary. This is used by WholeProgramDevirt if we
|
|
|
|
/// were unable to devirtualize a checked call.
|
|
|
|
void addTypeTest(GlobalValue::GUID Guid) {
|
|
|
|
if (!TIdInfo)
|
2019-08-15 17:54:37 +02:00
|
|
|
TIdInfo = std::make_unique<TypeIdInfo>();
|
2017-03-04 02:23:30 +01:00
|
|
|
TIdInfo->TypeTests.push_back(Guid);
|
|
|
|
}
|
2018-02-19 16:14:50 +01:00
|
|
|
|
2018-05-26 04:34:13 +02:00
|
|
|
const TypeIdInfo *getTypeIdInfo() const { return TIdInfo.get(); };
|
|
|
|
|
2018-02-19 16:14:50 +01:00
|
|
|
friend struct GraphTraits<ValueInfo>;
|
2017-02-10 23:29:38 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
template <> struct DenseMapInfo<FunctionSummary::VFuncId> {
|
2017-02-11 04:19:22 +01:00
|
|
|
static FunctionSummary::VFuncId getEmptyKey() { return {0, uint64_t(-1)}; }
|
2017-05-13 00:25:07 +02:00
|
|
|
|
2017-02-11 04:19:22 +01:00
|
|
|
static FunctionSummary::VFuncId getTombstoneKey() {
|
2017-02-10 23:29:38 +01:00
|
|
|
return {0, uint64_t(-2)};
|
|
|
|
}
|
2017-05-13 00:25:07 +02:00
|
|
|
|
2017-02-10 23:29:38 +01:00
|
|
|
static bool isEqual(FunctionSummary::VFuncId L, FunctionSummary::VFuncId R) {
|
|
|
|
return L.GUID == R.GUID && L.Offset == R.Offset;
|
|
|
|
}
|
2017-05-13 00:25:07 +02:00
|
|
|
|
2017-02-10 23:29:38 +01:00
|
|
|
static unsigned getHashValue(FunctionSummary::VFuncId I) { return I.GUID; }
|
|
|
|
};
|
|
|
|
|
|
|
|
template <> struct DenseMapInfo<FunctionSummary::ConstVCall> {
|
2017-02-11 04:19:22 +01:00
|
|
|
static FunctionSummary::ConstVCall getEmptyKey() {
|
2017-02-10 23:29:38 +01:00
|
|
|
return {{0, uint64_t(-1)}, {}};
|
|
|
|
}
|
2017-05-13 00:25:07 +02:00
|
|
|
|
2017-02-11 04:19:22 +01:00
|
|
|
static FunctionSummary::ConstVCall getTombstoneKey() {
|
2017-02-10 23:29:38 +01:00
|
|
|
return {{0, uint64_t(-2)}, {}};
|
|
|
|
}
|
2017-05-13 00:25:07 +02:00
|
|
|
|
2017-02-10 23:29:38 +01:00
|
|
|
static bool isEqual(FunctionSummary::ConstVCall L,
|
|
|
|
FunctionSummary::ConstVCall R) {
|
|
|
|
return DenseMapInfo<FunctionSummary::VFuncId>::isEqual(L.VFunc, R.VFunc) &&
|
|
|
|
L.Args == R.Args;
|
|
|
|
}
|
2017-05-13 00:25:07 +02:00
|
|
|
|
2017-02-10 23:29:38 +01:00
|
|
|
static unsigned getHashValue(FunctionSummary::ConstVCall I) {
|
|
|
|
return I.VFunc.GUID;
|
|
|
|
}
|
2016-03-14 22:18:10 +01:00
|
|
|
};
|
|
|
|
|
[ThinLTO] Add summary entries for index-based WPD
Summary:
If LTOUnit splitting is disabled, the module summary analysis computes
the summary information necessary to perform single implementation
devirtualization during the thin link with the index and no IR. The
information collected from the regular LTO IR in the current hybrid WPD
algorithm is summarized, including:
1) For vtable definitions, record the function pointers and their offset
within the vtable initializer (subsumes the information collected from
IR by tryFindVirtualCallTargets).
2) A record for each type metadata summarizing the vtable definitions
decorated with that metadata (subsumes the TypeIdentiferMap collected
from IR).
Also added are the necessary bitcode records, and the corresponding
assembly support.
The follow-on index-based WPD patch is D55153.
Depends on D53890.
Reviewers: pcc
Subscribers: mehdi_amini, Prazek, inglorion, eraman, steven_wu, dexonsmith, arphaman, llvm-commits
Differential Revision: https://reviews.llvm.org/D54815
llvm-svn: 364960
2019-07-02 21:38:02 +02:00
|
|
|
/// The ValueInfo and offset for a function within a vtable definition
|
|
|
|
/// initializer array.
|
|
|
|
struct VirtFuncOffset {
|
|
|
|
VirtFuncOffset(ValueInfo VI, uint64_t Offset)
|
|
|
|
: FuncVI(VI), VTableOffset(Offset) {}
|
|
|
|
|
|
|
|
ValueInfo FuncVI;
|
|
|
|
uint64_t VTableOffset;
|
|
|
|
};
|
|
|
|
/// List of functions referenced by a particular vtable definition.
|
|
|
|
using VTableFuncList = std::vector<VirtFuncOffset>;
|
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Global variable summary information to aid decisions and
|
2016-03-14 22:18:10 +01:00
|
|
|
/// implementation of importing.
|
|
|
|
///
|
2019-07-05 17:25:05 +02:00
|
|
|
/// Global variable summary has two extra flag, telling if it is
|
|
|
|
/// readonly or writeonly. Both readonly and writeonly variables
|
|
|
|
/// can be optimized in the backed: readonly variables can be
|
|
|
|
/// const-folded, while writeonly vars can be completely eliminated
|
|
|
|
/// together with corresponding stores. We let both things happen
|
|
|
|
/// by means of internalizing such variables after ThinLTO import.
|
2016-03-14 22:18:10 +01:00
|
|
|
class GlobalVarSummary : public GlobalValueSummary {
|
[ThinLTO] Add summary entries for index-based WPD
Summary:
If LTOUnit splitting is disabled, the module summary analysis computes
the summary information necessary to perform single implementation
devirtualization during the thin link with the index and no IR. The
information collected from the regular LTO IR in the current hybrid WPD
algorithm is summarized, including:
1) For vtable definitions, record the function pointers and their offset
within the vtable initializer (subsumes the information collected from
IR by tryFindVirtualCallTargets).
2) A record for each type metadata summarizing the vtable definitions
decorated with that metadata (subsumes the TypeIdentiferMap collected
from IR).
Also added are the necessary bitcode records, and the corresponding
assembly support.
The follow-on index-based WPD patch is D55153.
Depends on D53890.
Reviewers: pcc
Subscribers: mehdi_amini, Prazek, inglorion, eraman, steven_wu, dexonsmith, arphaman, llvm-commits
Differential Revision: https://reviews.llvm.org/D54815
llvm-svn: 364960
2019-07-02 21:38:02 +02:00
|
|
|
private:
|
|
|
|
/// For vtable definitions this holds the list of functions and
|
|
|
|
/// their corresponding offsets within the initializer array.
|
|
|
|
std::unique_ptr<VTableFuncList> VTableFuncs;
|
|
|
|
|
2018-11-13 18:35:04 +01:00
|
|
|
public:
|
2018-11-16 08:08:00 +01:00
|
|
|
struct GVarFlags {
|
2019-07-05 17:25:05 +02:00
|
|
|
GVarFlags(bool ReadOnly, bool WriteOnly)
|
|
|
|
: MaybeReadOnly(ReadOnly), MaybeWriteOnly(WriteOnly) {}
|
|
|
|
|
|
|
|
// In permodule summaries both MaybeReadOnly and MaybeWriteOnly
|
|
|
|
// bits are set, because attribute propagation occurs later on
|
|
|
|
// thin link phase.
|
|
|
|
unsigned MaybeReadOnly : 1;
|
|
|
|
unsigned MaybeWriteOnly : 1;
|
2018-11-16 08:08:00 +01:00
|
|
|
} VarFlags;
|
|
|
|
|
|
|
|
GlobalVarSummary(GVFlags Flags, GVarFlags VarFlags,
|
|
|
|
std::vector<ValueInfo> Refs)
|
|
|
|
: GlobalValueSummary(GlobalVarKind, Flags, std::move(Refs)),
|
|
|
|
VarFlags(VarFlags) {}
|
2016-03-14 22:18:10 +01:00
|
|
|
|
|
|
|
/// Check if this is a global variable summary.
|
|
|
|
static bool classof(const GlobalValueSummary *GVS) {
|
|
|
|
return GVS->getSummaryKind() == GlobalVarKind;
|
|
|
|
}
|
2018-11-16 08:08:00 +01:00
|
|
|
|
|
|
|
GVarFlags varflags() const { return VarFlags; }
|
2019-07-05 17:25:05 +02:00
|
|
|
void setReadOnly(bool RO) { VarFlags.MaybeReadOnly = RO; }
|
|
|
|
void setWriteOnly(bool WO) { VarFlags.MaybeWriteOnly = WO; }
|
|
|
|
bool maybeReadOnly() const { return VarFlags.MaybeReadOnly; }
|
|
|
|
bool maybeWriteOnly() const { return VarFlags.MaybeWriteOnly; }
|
[ThinLTO] Add summary entries for index-based WPD
Summary:
If LTOUnit splitting is disabled, the module summary analysis computes
the summary information necessary to perform single implementation
devirtualization during the thin link with the index and no IR. The
information collected from the regular LTO IR in the current hybrid WPD
algorithm is summarized, including:
1) For vtable definitions, record the function pointers and their offset
within the vtable initializer (subsumes the information collected from
IR by tryFindVirtualCallTargets).
2) A record for each type metadata summarizing the vtable definitions
decorated with that metadata (subsumes the TypeIdentiferMap collected
from IR).
Also added are the necessary bitcode records, and the corresponding
assembly support.
The follow-on index-based WPD patch is D55153.
Depends on D53890.
Reviewers: pcc
Subscribers: mehdi_amini, Prazek, inglorion, eraman, steven_wu, dexonsmith, arphaman, llvm-commits
Differential Revision: https://reviews.llvm.org/D54815
llvm-svn: 364960
2019-07-02 21:38:02 +02:00
|
|
|
|
|
|
|
void setVTableFuncs(VTableFuncList Funcs) {
|
|
|
|
assert(!VTableFuncs);
|
2019-08-15 17:54:37 +02:00
|
|
|
VTableFuncs = std::make_unique<VTableFuncList>(std::move(Funcs));
|
[ThinLTO] Add summary entries for index-based WPD
Summary:
If LTOUnit splitting is disabled, the module summary analysis computes
the summary information necessary to perform single implementation
devirtualization during the thin link with the index and no IR. The
information collected from the regular LTO IR in the current hybrid WPD
algorithm is summarized, including:
1) For vtable definitions, record the function pointers and their offset
within the vtable initializer (subsumes the information collected from
IR by tryFindVirtualCallTargets).
2) A record for each type metadata summarizing the vtable definitions
decorated with that metadata (subsumes the TypeIdentiferMap collected
from IR).
Also added are the necessary bitcode records, and the corresponding
assembly support.
The follow-on index-based WPD patch is D55153.
Depends on D53890.
Reviewers: pcc
Subscribers: mehdi_amini, Prazek, inglorion, eraman, steven_wu, dexonsmith, arphaman, llvm-commits
Differential Revision: https://reviews.llvm.org/D54815
llvm-svn: 364960
2019-07-02 21:38:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ArrayRef<VirtFuncOffset> vTableFuncs() const {
|
|
|
|
if (VTableFuncs)
|
|
|
|
return *VTableFuncs;
|
|
|
|
return {};
|
|
|
|
}
|
2016-03-14 22:18:10 +01:00
|
|
|
};
|
|
|
|
|
2017-01-05 04:39:00 +01:00
|
|
|
struct TypeTestResolution {
|
|
|
|
/// Specifies which kind of type check we should emit for this byte array.
|
|
|
|
/// See http://clang.llvm.org/docs/ControlFlowIntegrityDesign.html for full
|
|
|
|
/// details on each kind of check; the enumerators are described with
|
|
|
|
/// reference to that document.
|
|
|
|
enum Kind {
|
|
|
|
Unsat, ///< Unsatisfiable type (i.e. no global has this type metadata)
|
|
|
|
ByteArray, ///< Test a byte array (first example)
|
|
|
|
Inline, ///< Inlined bit vector ("Short Inline Bit Vectors")
|
|
|
|
Single, ///< Single element (last example in "Short Inline Bit Vectors")
|
|
|
|
AllOnes, ///< All-ones bit vector ("Eliminating Bit Vector Checks for
|
|
|
|
/// All-Ones Bit Vectors")
|
|
|
|
} TheKind = Unsat;
|
|
|
|
|
2017-01-11 22:32:10 +01:00
|
|
|
/// Range of size-1 expressed as a bit width. For example, if the size is in
|
|
|
|
/// range [1,256], this number will be 8. This helps generate the most compact
|
2017-01-05 04:39:00 +01:00
|
|
|
/// instruction sequences.
|
2017-01-11 22:32:10 +01:00
|
|
|
unsigned SizeM1BitWidth = 0;
|
2017-09-12 00:49:10 +02:00
|
|
|
|
|
|
|
// The following fields are only used if the target does not support the use
|
|
|
|
// of absolute symbols to store constants. Their meanings are the same as the
|
|
|
|
// corresponding fields in LowerTypeTestsModule::TypeIdLowering in
|
|
|
|
// LowerTypeTests.cpp.
|
|
|
|
|
|
|
|
uint64_t AlignLog2 = 0;
|
|
|
|
uint64_t SizeM1 = 0;
|
|
|
|
uint8_t BitMask = 0;
|
|
|
|
uint64_t InlineBits = 0;
|
2017-01-05 04:39:00 +01:00
|
|
|
};
|
|
|
|
|
2017-02-13 20:26:18 +01:00
|
|
|
struct WholeProgramDevirtResolution {
|
|
|
|
enum Kind {
|
2018-03-09 20:11:44 +01:00
|
|
|
Indir, ///< Just do a regular virtual call
|
|
|
|
SingleImpl, ///< Single implementation devirtualization
|
|
|
|
BranchFunnel, ///< When retpoline mitigation is enabled, use a branch funnel
|
|
|
|
///< that is defined in the merged module. Otherwise same as
|
|
|
|
///< Indir.
|
2017-02-13 20:26:18 +01:00
|
|
|
} TheKind = Indir;
|
|
|
|
|
|
|
|
std::string SingleImplName;
|
|
|
|
|
|
|
|
struct ByArg {
|
|
|
|
enum Kind {
|
|
|
|
Indir, ///< Just do a regular virtual call
|
|
|
|
UniformRetVal, ///< Uniform return value optimization
|
|
|
|
UniqueRetVal, ///< Unique return value optimization
|
|
|
|
VirtualConstProp, ///< Virtual constant propagation
|
|
|
|
} TheKind = Indir;
|
|
|
|
|
|
|
|
/// Additional information for the resolution:
|
|
|
|
/// - UniformRetVal: the uniform return value.
|
|
|
|
/// - UniqueRetVal: the return value associated with the unique vtable (0 or
|
|
|
|
/// 1).
|
|
|
|
uint64_t Info = 0;
|
2017-09-12 00:34:42 +02:00
|
|
|
|
|
|
|
// The following fields are only used if the target does not support the use
|
|
|
|
// of absolute symbols to store constants.
|
|
|
|
|
|
|
|
uint32_t Byte = 0;
|
|
|
|
uint32_t Bit = 0;
|
2017-02-13 20:26:18 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/// Resolutions for calls with all constant integer arguments (excluding the
|
|
|
|
/// first argument, "this"), where the key is the argument vector.
|
|
|
|
std::map<std::vector<uint64_t>, ByArg> ResByArg;
|
|
|
|
};
|
|
|
|
|
2017-01-05 04:39:00 +01:00
|
|
|
struct TypeIdSummary {
|
|
|
|
TypeTestResolution TTRes;
|
2017-02-13 20:26:18 +01:00
|
|
|
|
|
|
|
/// Mapping from byte offset to whole-program devirt resolution for that
|
|
|
|
/// (typeid, byte offset) pair.
|
|
|
|
std::map<uint64_t, WholeProgramDevirtResolution> WPDRes;
|
2017-01-05 04:39:00 +01:00
|
|
|
};
|
|
|
|
|
2016-04-01 07:33:11 +02:00
|
|
|
/// 160 bits SHA1
|
2017-05-13 00:25:07 +02:00
|
|
|
using ModuleHash = std::array<uint32_t, 5>;
|
2016-04-01 07:33:11 +02:00
|
|
|
|
2016-04-24 16:57:11 +02:00
|
|
|
/// Type used for iterating through the global value summary map.
|
2017-05-13 00:25:07 +02:00
|
|
|
using const_gvsummary_iterator = GlobalValueSummaryMapTy::const_iterator;
|
|
|
|
using gvsummary_iterator = GlobalValueSummaryMapTy::iterator;
|
2016-03-14 22:18:10 +01:00
|
|
|
|
|
|
|
/// String table to hold/own module path strings, which additionally holds the
|
2016-04-01 07:33:11 +02:00
|
|
|
/// module ID assigned to each module during the plugin step, as well as a hash
|
|
|
|
/// of the module. The StringMap makes a copy of and owns inserted strings.
|
2017-05-13 00:25:07 +02:00
|
|
|
using ModulePathStringTableTy = StringMap<std::pair<uint64_t, ModuleHash>>;
|
2016-03-14 22:18:10 +01:00
|
|
|
|
2016-04-25 23:09:51 +02:00
|
|
|
/// Map of global value GUID to its summary, used to identify values defined in
|
|
|
|
/// a particular module, and provide efficient access to their summary.
|
2017-07-10 22:12:54 +02:00
|
|
|
using GVSummaryMapTy = DenseMap<GlobalValue::GUID, GlobalValueSummary *>;
|
2016-04-25 23:09:51 +02:00
|
|
|
|
[ThinLTO] Efficiency fix for writing type id records in per-module indexes
Summary:
In D49565/r337503, the type id record writing was fixed so that only
referenced type ids were emitted into each per-module index for ThinLTO
distributed builds. However, this still left an efficiency issue: each
per-module index checked all type ids for membership in the referenced
set, yielding O(M*N) performance (M indexes and N type ids).
Change the TypeIdMap in the summary to be indexed by GUID, to facilitate
correlating with type identifier GUIDs referenced in the function
summary TypeIdInfo structures. This allowed simplifying other
places where a map from type id GUID to type id map entry was previously
being used to aid this correlation.
Also fix AsmWriter code to handle the rare case of type id GUID
collision.
For a large internal application, this reduced the thin link time by
almost 15%.
Reviewers: pcc, vitalybuka
Subscribers: mehdi_amini, inglorion, steven_wu, dexonsmith, llvm-commits
Differential Revision: https://reviews.llvm.org/D51330
llvm-svn: 343021
2018-09-25 22:14:40 +02:00
|
|
|
/// Map of a type GUID to type id string and summary (multimap used
|
|
|
|
/// in case of GUID conflicts).
|
|
|
|
using TypeIdSummaryMapTy =
|
|
|
|
std::multimap<GlobalValue::GUID, std::pair<std::string, TypeIdSummary>>;
|
|
|
|
|
[ThinLTO] Add summary entries for index-based WPD
Summary:
If LTOUnit splitting is disabled, the module summary analysis computes
the summary information necessary to perform single implementation
devirtualization during the thin link with the index and no IR. The
information collected from the regular LTO IR in the current hybrid WPD
algorithm is summarized, including:
1) For vtable definitions, record the function pointers and their offset
within the vtable initializer (subsumes the information collected from
IR by tryFindVirtualCallTargets).
2) A record for each type metadata summarizing the vtable definitions
decorated with that metadata (subsumes the TypeIdentiferMap collected
from IR).
Also added are the necessary bitcode records, and the corresponding
assembly support.
The follow-on index-based WPD patch is D55153.
Depends on D53890.
Reviewers: pcc
Subscribers: mehdi_amini, Prazek, inglorion, eraman, steven_wu, dexonsmith, arphaman, llvm-commits
Differential Revision: https://reviews.llvm.org/D54815
llvm-svn: 364960
2019-07-02 21:38:02 +02:00
|
|
|
/// The following data structures summarize type metadata information.
|
|
|
|
/// For type metadata overview see https://llvm.org/docs/TypeMetadata.html.
|
|
|
|
/// Each type metadata includes both the type identifier and the offset of
|
|
|
|
/// the address point of the type (the address held by objects of that type
|
|
|
|
/// which may not be the beginning of the virtual table). Vtable definitions
|
|
|
|
/// are decorated with type metadata for the types they are compatible with.
|
|
|
|
///
|
|
|
|
/// Holds information about vtable definitions decorated with type metadata:
|
|
|
|
/// the vtable definition value and its address point offset in a type
|
|
|
|
/// identifier metadata it is decorated (compatible) with.
|
|
|
|
struct TypeIdOffsetVtableInfo {
|
|
|
|
TypeIdOffsetVtableInfo(uint64_t Offset, ValueInfo VI)
|
|
|
|
: AddressPointOffset(Offset), VTableVI(VI) {}
|
|
|
|
|
|
|
|
uint64_t AddressPointOffset;
|
|
|
|
ValueInfo VTableVI;
|
|
|
|
};
|
|
|
|
/// List of vtable definitions decorated by a particular type identifier,
|
|
|
|
/// and their corresponding offsets in that type identifier's metadata.
|
|
|
|
/// Note that each type identifier may be compatible with multiple vtables, due
|
|
|
|
/// to inheritance, which is why this is a vector.
|
|
|
|
using TypeIdCompatibleVtableInfo = std::vector<TypeIdOffsetVtableInfo>;
|
|
|
|
|
2016-03-14 22:18:10 +01:00
|
|
|
/// Class to hold module path string table and global value map,
|
|
|
|
/// and encapsulate methods for operating on them.
|
2016-03-15 01:04:37 +01:00
|
|
|
class ModuleSummaryIndex {
|
2016-03-14 22:18:10 +01:00
|
|
|
private:
|
2016-04-24 16:57:11 +02:00
|
|
|
/// Map from value name to list of summary instances for values of that
|
2016-03-14 22:18:10 +01:00
|
|
|
/// name (may be duplicates in the COMDAT case, e.g.).
|
2016-04-24 16:57:11 +02:00
|
|
|
GlobalValueSummaryMapTy GlobalValueMap;
|
2016-03-14 22:18:10 +01:00
|
|
|
|
|
|
|
/// Holds strings for combined index, mapping to the corresponding module ID.
|
|
|
|
ModulePathStringTableTy ModulePathStringTable;
|
|
|
|
|
[ThinLTO] Efficiency fix for writing type id records in per-module indexes
Summary:
In D49565/r337503, the type id record writing was fixed so that only
referenced type ids were emitted into each per-module index for ThinLTO
distributed builds. However, this still left an efficiency issue: each
per-module index checked all type ids for membership in the referenced
set, yielding O(M*N) performance (M indexes and N type ids).
Change the TypeIdMap in the summary to be indexed by GUID, to facilitate
correlating with type identifier GUIDs referenced in the function
summary TypeIdInfo structures. This allowed simplifying other
places where a map from type id GUID to type id map entry was previously
being used to aid this correlation.
Also fix AsmWriter code to handle the rare case of type id GUID
collision.
For a large internal application, this reduced the thin link time by
almost 15%.
Reviewers: pcc, vitalybuka
Subscribers: mehdi_amini, inglorion, steven_wu, dexonsmith, llvm-commits
Differential Revision: https://reviews.llvm.org/D51330
llvm-svn: 343021
2018-09-25 22:14:40 +02:00
|
|
|
/// Mapping from type identifier GUIDs to type identifier and its summary
|
[ThinLTO] Add summary entries for index-based WPD
Summary:
If LTOUnit splitting is disabled, the module summary analysis computes
the summary information necessary to perform single implementation
devirtualization during the thin link with the index and no IR. The
information collected from the regular LTO IR in the current hybrid WPD
algorithm is summarized, including:
1) For vtable definitions, record the function pointers and their offset
within the vtable initializer (subsumes the information collected from
IR by tryFindVirtualCallTargets).
2) A record for each type metadata summarizing the vtable definitions
decorated with that metadata (subsumes the TypeIdentiferMap collected
from IR).
Also added are the necessary bitcode records, and the corresponding
assembly support.
The follow-on index-based WPD patch is D55153.
Depends on D53890.
Reviewers: pcc
Subscribers: mehdi_amini, Prazek, inglorion, eraman, steven_wu, dexonsmith, arphaman, llvm-commits
Differential Revision: https://reviews.llvm.org/D54815
llvm-svn: 364960
2019-07-02 21:38:02 +02:00
|
|
|
/// information. Produced by thin link.
|
[ThinLTO] Efficiency fix for writing type id records in per-module indexes
Summary:
In D49565/r337503, the type id record writing was fixed so that only
referenced type ids were emitted into each per-module index for ThinLTO
distributed builds. However, this still left an efficiency issue: each
per-module index checked all type ids for membership in the referenced
set, yielding O(M*N) performance (M indexes and N type ids).
Change the TypeIdMap in the summary to be indexed by GUID, to facilitate
correlating with type identifier GUIDs referenced in the function
summary TypeIdInfo structures. This allowed simplifying other
places where a map from type id GUID to type id map entry was previously
being used to aid this correlation.
Also fix AsmWriter code to handle the rare case of type id GUID
collision.
For a large internal application, this reduced the thin link time by
almost 15%.
Reviewers: pcc, vitalybuka
Subscribers: mehdi_amini, inglorion, steven_wu, dexonsmith, llvm-commits
Differential Revision: https://reviews.llvm.org/D51330
llvm-svn: 343021
2018-09-25 22:14:40 +02:00
|
|
|
TypeIdSummaryMapTy TypeIdMap;
|
2017-01-05 04:39:00 +01:00
|
|
|
|
[ThinLTO] Add summary entries for index-based WPD
Summary:
If LTOUnit splitting is disabled, the module summary analysis computes
the summary information necessary to perform single implementation
devirtualization during the thin link with the index and no IR. The
information collected from the regular LTO IR in the current hybrid WPD
algorithm is summarized, including:
1) For vtable definitions, record the function pointers and their offset
within the vtable initializer (subsumes the information collected from
IR by tryFindVirtualCallTargets).
2) A record for each type metadata summarizing the vtable definitions
decorated with that metadata (subsumes the TypeIdentiferMap collected
from IR).
Also added are the necessary bitcode records, and the corresponding
assembly support.
The follow-on index-based WPD patch is D55153.
Depends on D53890.
Reviewers: pcc
Subscribers: mehdi_amini, Prazek, inglorion, eraman, steven_wu, dexonsmith, arphaman, llvm-commits
Differential Revision: https://reviews.llvm.org/D54815
llvm-svn: 364960
2019-07-02 21:38:02 +02:00
|
|
|
/// Mapping from type identifier to information about vtables decorated
|
|
|
|
/// with that type identifier's metadata. Produced by per module summary
|
|
|
|
/// analysis and consumed by thin link. For more information, see description
|
|
|
|
/// above where TypeIdCompatibleVtableInfo is defined.
|
|
|
|
std::map<std::string, TypeIdCompatibleVtableInfo> TypeIdCompatibleVtableMap;
|
|
|
|
|
SamplePGO ThinLTO ICP fix for local functions.
Summary:
In SamplePGO, if the profile is collected from non-LTO binary, and used to drive ThinLTO, the indirect call promotion may fail because ThinLTO adjusts local function names to avoid conflicts. There are two places of where the mismatch can happen:
1. thin-link prepends SourceFileName to front of FuncName to build the GUID (GlobalValue::getGlobalIdentifier). Unlike instrumentation FDO, SamplePGO does not use the PGOFuncName scheme and therefore the indirect call target profile data contains a hash of the OriginalName.
2. backend compiler promotes some local functions to global and appends .llvm.{$ModuleHash} to the end of the FuncName to derive PromotedFunctionName
This patch tries at the best effort to find the GUID from the original local function name (in profile), and use that in ICP promotion, and in SamplePGO matching that happens in the backend after importing/inlining:
1. in thin-link, it builds the map from OriginalName to GUID so that when thin-link reads in indirect call target profile (represented by OriginalName), it knows which GUID to import.
2. in backend compiler, if sample profile reader cannot find a profile match for PromotedFunctionName, it will try to find if there is a match for OriginalFunctionName.
3. in backend compiler, we build symbol table entry for OriginalFunctionName and pointer to the same symbol of PromotedFunctionName, so that ICP can find the correct target to promote.
Reviewers: mehdi_amini, tejohnson
Reviewed By: tejohnson
Subscribers: llvm-commits, Prazek
Differential Revision: https://reviews.llvm.org/D30754
llvm-svn: 297757
2017-03-14 18:33:01 +01:00
|
|
|
/// Mapping from original ID to GUID. If original ID can map to multiple
|
|
|
|
/// GUIDs, it will be mapped to 0.
|
|
|
|
std::map<GlobalValue::GUID, GlobalValue::GUID> OidGuidMap;
|
|
|
|
|
2017-06-01 22:30:06 +02:00
|
|
|
/// Indicates that summary-based GlobalValue GC has run, and values with
|
|
|
|
/// GVFlags::Live==false are really dead. Otherwise, all values must be
|
|
|
|
/// considered live.
|
|
|
|
bool WithGlobalValueDeadStripping = false;
|
|
|
|
|
2019-11-07 13:13:35 +01:00
|
|
|
/// Indicates that summary-based attribute propagation has run and
|
|
|
|
/// GVarFlags::MaybeReadonly / GVarFlags::MaybeWriteonly are really
|
|
|
|
/// read/write only.
|
|
|
|
bool WithAttributePropagation = false;
|
|
|
|
|
2018-12-13 20:54:27 +01:00
|
|
|
/// Indicates that summary-based synthetic entry count propagation has run
|
|
|
|
bool HasSyntheticEntryCounts = false;
|
|
|
|
|
2018-02-17 00:38:22 +01:00
|
|
|
/// Indicates that distributed backend should skip compilation of the
|
|
|
|
/// module. Flag is suppose to be set by distributed ThinLTO indexing
|
|
|
|
/// when it detected that the module is not needed during the final
|
|
|
|
/// linking. As result distributed backend should just output a minimal
|
|
|
|
/// valid object file.
|
|
|
|
bool SkipModuleByDistributedBackend = false;
|
|
|
|
|
2018-06-07 00:22:01 +02:00
|
|
|
/// If true then we're performing analysis of IR module, or parsing along with
|
|
|
|
/// the IR from assembly. The value of 'false' means we're reading summary
|
|
|
|
/// from BC or YAML source. Affects the type of value stored in NameOrGV
|
|
|
|
/// union.
|
|
|
|
bool HaveGVs;
|
2018-01-22 14:35:40 +01:00
|
|
|
|
[LTO] Record whether LTOUnit splitting is enabled in index
Summary:
Records in the module summary index whether the bitcode was compiled
with the option necessary to enable splitting the LTO unit
(e.g. -fsanitize=cfi, -fwhole-program-vtables, or -fsplit-lto-unit).
The information is passed down to the ModuleSummaryIndex builder via a
new module flag "EnableSplitLTOUnit", which is propagated onto a flag
on the summary index.
This is then used during the LTO link to check whether all linked
summaries were built with the same value of this flag. If not, an error
is issued when we detect a situation requiring whole program visibility
of the class hierarchy. This is the case when both of the following
conditions are met:
1) We are performing LowerTypeTests or Whole Program Devirtualization.
2) There are type tests or type checked loads in the code.
Note I have also changed the ThinLTOBitcodeWriter to also gate the
module splitting on the value of this flag.
Reviewers: pcc
Subscribers: ormris, mehdi_amini, Prazek, inglorion, eraman, steven_wu, dexonsmith, arphaman, dang, llvm-commits
Differential Revision: https://reviews.llvm.org/D53890
llvm-svn: 350948
2019-01-11 19:31:57 +01:00
|
|
|
// True if the index was created for a module compiled with -fsplit-lto-unit.
|
|
|
|
bool EnableSplitLTOUnit;
|
|
|
|
|
|
|
|
// True if some of the modules were compiled with -fsplit-lto-unit and
|
|
|
|
// some were not. Set when the combined index is created during the thin link.
|
|
|
|
bool PartiallySplitLTOUnits = false;
|
|
|
|
|
2017-06-16 02:18:29 +02:00
|
|
|
std::set<std::string> CfiFunctionDefs;
|
|
|
|
std::set<std::string> CfiFunctionDecls;
|
|
|
|
|
2018-06-26 04:29:08 +02:00
|
|
|
// Used in cases where we want to record the name of a global, but
|
|
|
|
// don't have the string owned elsewhere (e.g. the Strtab on a module).
|
|
|
|
StringSaver Saver;
|
|
|
|
BumpPtrAllocator Alloc;
|
|
|
|
|
2017-01-05 04:39:00 +01:00
|
|
|
// YAML I/O support.
|
|
|
|
friend yaml::MappingTraits<ModuleSummaryIndex>;
|
|
|
|
|
2017-05-04 20:03:25 +02:00
|
|
|
GlobalValueSummaryMapTy::value_type *
|
|
|
|
getOrInsertValuePtr(GlobalValue::GUID GUID) {
|
2018-06-07 00:22:01 +02:00
|
|
|
return &*GlobalValueMap.emplace(GUID, GlobalValueSummaryInfo(HaveGVs))
|
|
|
|
.first;
|
2017-05-04 20:03:25 +02:00
|
|
|
}
|
|
|
|
|
2016-03-14 22:18:10 +01:00
|
|
|
public:
|
2018-06-07 00:22:01 +02:00
|
|
|
// See HaveGVs variable comment.
|
[LTO] Record whether LTOUnit splitting is enabled in index
Summary:
Records in the module summary index whether the bitcode was compiled
with the option necessary to enable splitting the LTO unit
(e.g. -fsanitize=cfi, -fwhole-program-vtables, or -fsplit-lto-unit).
The information is passed down to the ModuleSummaryIndex builder via a
new module flag "EnableSplitLTOUnit", which is propagated onto a flag
on the summary index.
This is then used during the LTO link to check whether all linked
summaries were built with the same value of this flag. If not, an error
is issued when we detect a situation requiring whole program visibility
of the class hierarchy. This is the case when both of the following
conditions are met:
1) We are performing LowerTypeTests or Whole Program Devirtualization.
2) There are type tests or type checked loads in the code.
Note I have also changed the ThinLTOBitcodeWriter to also gate the
module splitting on the value of this flag.
Reviewers: pcc
Subscribers: ormris, mehdi_amini, Prazek, inglorion, eraman, steven_wu, dexonsmith, arphaman, dang, llvm-commits
Differential Revision: https://reviews.llvm.org/D53890
llvm-svn: 350948
2019-01-11 19:31:57 +01:00
|
|
|
ModuleSummaryIndex(bool HaveGVs, bool EnableSplitLTOUnit = false)
|
|
|
|
: HaveGVs(HaveGVs), EnableSplitLTOUnit(EnableSplitLTOUnit), Saver(Alloc) {
|
|
|
|
}
|
2018-01-22 14:35:40 +01:00
|
|
|
|
2018-06-07 00:22:01 +02:00
|
|
|
bool haveGVs() const { return HaveGVs; }
|
2018-01-22 14:35:40 +01:00
|
|
|
|
2016-04-24 16:57:11 +02:00
|
|
|
gvsummary_iterator begin() { return GlobalValueMap.begin(); }
|
|
|
|
const_gvsummary_iterator begin() const { return GlobalValueMap.begin(); }
|
|
|
|
gvsummary_iterator end() { return GlobalValueMap.end(); }
|
|
|
|
const_gvsummary_iterator end() const { return GlobalValueMap.end(); }
|
2017-01-05 22:34:18 +01:00
|
|
|
size_t size() const { return GlobalValueMap.size(); }
|
2016-03-14 22:18:10 +01:00
|
|
|
|
2018-02-19 16:14:50 +01:00
|
|
|
/// Convenience function for doing a DFS on a ValueInfo. Marks the function in
|
|
|
|
/// the FunctionHasParent map.
|
|
|
|
static void discoverNodes(ValueInfo V,
|
|
|
|
std::map<ValueInfo, bool> &FunctionHasParent) {
|
|
|
|
if (!V.getSummaryList().size())
|
|
|
|
return; // skip external functions that don't have summaries
|
|
|
|
|
|
|
|
// Mark discovered if we haven't yet
|
|
|
|
auto S = FunctionHasParent.emplace(V, false);
|
|
|
|
|
|
|
|
// Stop if we've already discovered this node
|
|
|
|
if (!S.second)
|
|
|
|
return;
|
|
|
|
|
|
|
|
FunctionSummary *F =
|
|
|
|
dyn_cast<FunctionSummary>(V.getSummaryList().front().get());
|
|
|
|
assert(F != nullptr && "Expected FunctionSummary node");
|
|
|
|
|
|
|
|
for (auto &C : F->calls()) {
|
|
|
|
// Insert node if necessary
|
|
|
|
auto S = FunctionHasParent.emplace(C.first, true);
|
|
|
|
|
|
|
|
// Skip nodes that we're sure have parents
|
|
|
|
if (!S.second && S.first->second)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (S.second)
|
|
|
|
discoverNodes(C.first, FunctionHasParent);
|
|
|
|
else
|
|
|
|
S.first->second = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Calculate the callgraph root
|
|
|
|
FunctionSummary calculateCallGraphRoot() {
|
|
|
|
// Functions that have a parent will be marked in FunctionHasParent pair.
|
|
|
|
// Once we've marked all functions, the functions in the map that are false
|
|
|
|
// have no parent (so they're the roots)
|
|
|
|
std::map<ValueInfo, bool> FunctionHasParent;
|
|
|
|
|
|
|
|
for (auto &S : *this) {
|
|
|
|
// Skip external functions
|
|
|
|
if (!S.second.SummaryList.size() ||
|
|
|
|
!isa<FunctionSummary>(S.second.SummaryList.front().get()))
|
|
|
|
continue;
|
2018-06-07 00:22:01 +02:00
|
|
|
discoverNodes(ValueInfo(HaveGVs, &S), FunctionHasParent);
|
2018-02-19 16:14:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<FunctionSummary::EdgeTy> Edges;
|
|
|
|
// create edges to all roots in the Index
|
|
|
|
for (auto &P : FunctionHasParent) {
|
|
|
|
if (P.second)
|
|
|
|
continue; // skip over non-root nodes
|
|
|
|
Edges.push_back(std::make_pair(P.first, CalleeInfo{}));
|
|
|
|
}
|
|
|
|
if (Edges.empty()) {
|
|
|
|
// Failed to find root - return an empty node
|
|
|
|
return FunctionSummary::makeDummyFunctionSummary({});
|
|
|
|
}
|
|
|
|
auto CallGraphRoot = FunctionSummary::makeDummyFunctionSummary(Edges);
|
|
|
|
return CallGraphRoot;
|
|
|
|
}
|
|
|
|
|
2017-06-01 22:30:06 +02:00
|
|
|
bool withGlobalValueDeadStripping() const {
|
|
|
|
return WithGlobalValueDeadStripping;
|
|
|
|
}
|
|
|
|
void setWithGlobalValueDeadStripping() {
|
|
|
|
WithGlobalValueDeadStripping = true;
|
|
|
|
}
|
|
|
|
|
2019-11-07 13:13:35 +01:00
|
|
|
bool withAttributePropagation() const { return WithAttributePropagation; }
|
|
|
|
void setWithAttributePropagation() {
|
|
|
|
WithAttributePropagation = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isReadOnly(const GlobalVarSummary *GVS) const {
|
|
|
|
return WithAttributePropagation && GVS->maybeReadOnly();
|
|
|
|
}
|
|
|
|
bool isWriteOnly(const GlobalVarSummary *GVS) const {
|
|
|
|
return WithAttributePropagation && GVS->maybeWriteOnly();
|
|
|
|
}
|
|
|
|
|
2018-12-13 20:54:27 +01:00
|
|
|
bool hasSyntheticEntryCounts() const { return HasSyntheticEntryCounts; }
|
|
|
|
void setHasSyntheticEntryCounts() { HasSyntheticEntryCounts = true; }
|
|
|
|
|
2018-02-17 00:38:22 +01:00
|
|
|
bool skipModuleByDistributedBackend() const {
|
|
|
|
return SkipModuleByDistributedBackend;
|
|
|
|
}
|
|
|
|
void setSkipModuleByDistributedBackend() {
|
|
|
|
SkipModuleByDistributedBackend = true;
|
|
|
|
}
|
|
|
|
|
[LTO] Record whether LTOUnit splitting is enabled in index
Summary:
Records in the module summary index whether the bitcode was compiled
with the option necessary to enable splitting the LTO unit
(e.g. -fsanitize=cfi, -fwhole-program-vtables, or -fsplit-lto-unit).
The information is passed down to the ModuleSummaryIndex builder via a
new module flag "EnableSplitLTOUnit", which is propagated onto a flag
on the summary index.
This is then used during the LTO link to check whether all linked
summaries were built with the same value of this flag. If not, an error
is issued when we detect a situation requiring whole program visibility
of the class hierarchy. This is the case when both of the following
conditions are met:
1) We are performing LowerTypeTests or Whole Program Devirtualization.
2) There are type tests or type checked loads in the code.
Note I have also changed the ThinLTOBitcodeWriter to also gate the
module splitting on the value of this flag.
Reviewers: pcc
Subscribers: ormris, mehdi_amini, Prazek, inglorion, eraman, steven_wu, dexonsmith, arphaman, dang, llvm-commits
Differential Revision: https://reviews.llvm.org/D53890
llvm-svn: 350948
2019-01-11 19:31:57 +01:00
|
|
|
bool enableSplitLTOUnit() const { return EnableSplitLTOUnit; }
|
|
|
|
void setEnableSplitLTOUnit() { EnableSplitLTOUnit = true; }
|
|
|
|
|
|
|
|
bool partiallySplitLTOUnits() const { return PartiallySplitLTOUnits; }
|
|
|
|
void setPartiallySplitLTOUnits() { PartiallySplitLTOUnits = true; }
|
|
|
|
|
2017-06-01 22:30:06 +02:00
|
|
|
bool isGlobalValueLive(const GlobalValueSummary *GVS) const {
|
|
|
|
return !WithGlobalValueDeadStripping || GVS->isLive();
|
|
|
|
}
|
2017-06-15 19:26:13 +02:00
|
|
|
bool isGUIDLive(GlobalValue::GUID GUID) const;
|
2017-06-01 22:30:06 +02:00
|
|
|
|
2018-05-26 04:34:13 +02:00
|
|
|
/// Return a ValueInfo for the index value_type (convenient when iterating
|
|
|
|
/// index).
|
|
|
|
ValueInfo getValueInfo(const GlobalValueSummaryMapTy::value_type &R) const {
|
2018-06-07 00:22:01 +02:00
|
|
|
return ValueInfo(HaveGVs, &R);
|
2018-05-26 04:34:13 +02:00
|
|
|
}
|
|
|
|
|
2017-05-04 20:03:25 +02:00
|
|
|
/// Return a ValueInfo for GUID if it exists, otherwise return ValueInfo().
|
|
|
|
ValueInfo getValueInfo(GlobalValue::GUID GUID) const {
|
|
|
|
auto I = GlobalValueMap.find(GUID);
|
2018-06-07 00:22:01 +02:00
|
|
|
return ValueInfo(HaveGVs, I == GlobalValueMap.end() ? nullptr : &*I);
|
2016-03-14 22:18:10 +01:00
|
|
|
}
|
|
|
|
|
2017-05-04 20:03:25 +02:00
|
|
|
/// Return a ValueInfo for \p GUID.
|
|
|
|
ValueInfo getOrInsertValueInfo(GlobalValue::GUID GUID) {
|
2018-06-07 00:22:01 +02:00
|
|
|
return ValueInfo(HaveGVs, getOrInsertValuePtr(GUID));
|
2018-01-22 14:35:40 +01:00
|
|
|
}
|
|
|
|
|
2018-06-26 04:29:08 +02:00
|
|
|
// Save a string in the Index. Use before passing Name to
|
|
|
|
// getOrInsertValueInfo when the string isn't owned elsewhere (e.g. on the
|
|
|
|
// module's Strtab).
|
2018-12-07 22:47:32 +01:00
|
|
|
StringRef saveString(StringRef String) { return Saver.save(String); }
|
2018-06-26 04:29:08 +02:00
|
|
|
|
2018-02-19 16:14:50 +01:00
|
|
|
/// Return a ValueInfo for \p GUID setting value \p Name.
|
2018-01-22 14:35:40 +01:00
|
|
|
ValueInfo getOrInsertValueInfo(GlobalValue::GUID GUID, StringRef Name) {
|
2018-06-07 00:22:01 +02:00
|
|
|
assert(!HaveGVs);
|
2018-01-22 14:35:40 +01:00
|
|
|
auto VP = getOrInsertValuePtr(GUID);
|
|
|
|
VP->second.U.Name = Name;
|
2018-06-07 00:22:01 +02:00
|
|
|
return ValueInfo(HaveGVs, VP);
|
2016-03-14 22:18:10 +01:00
|
|
|
}
|
|
|
|
|
2017-05-04 20:03:25 +02:00
|
|
|
/// Return a ValueInfo for \p GV and mark it as belonging to GV.
|
|
|
|
ValueInfo getOrInsertValueInfo(const GlobalValue *GV) {
|
2018-06-07 00:22:01 +02:00
|
|
|
assert(HaveGVs);
|
2017-05-04 20:03:25 +02:00
|
|
|
auto VP = getOrInsertValuePtr(GV->getGUID());
|
2018-01-22 14:35:40 +01:00
|
|
|
VP->second.U.GV = GV;
|
2018-06-07 00:22:01 +02:00
|
|
|
return ValueInfo(HaveGVs, VP);
|
2016-03-14 22:18:10 +01:00
|
|
|
}
|
|
|
|
|
SamplePGO ThinLTO ICP fix for local functions.
Summary:
In SamplePGO, if the profile is collected from non-LTO binary, and used to drive ThinLTO, the indirect call promotion may fail because ThinLTO adjusts local function names to avoid conflicts. There are two places of where the mismatch can happen:
1. thin-link prepends SourceFileName to front of FuncName to build the GUID (GlobalValue::getGlobalIdentifier). Unlike instrumentation FDO, SamplePGO does not use the PGOFuncName scheme and therefore the indirect call target profile data contains a hash of the OriginalName.
2. backend compiler promotes some local functions to global and appends .llvm.{$ModuleHash} to the end of the FuncName to derive PromotedFunctionName
This patch tries at the best effort to find the GUID from the original local function name (in profile), and use that in ICP promotion, and in SamplePGO matching that happens in the backend after importing/inlining:
1. in thin-link, it builds the map from OriginalName to GUID so that when thin-link reads in indirect call target profile (represented by OriginalName), it knows which GUID to import.
2. in backend compiler, if sample profile reader cannot find a profile match for PromotedFunctionName, it will try to find if there is a match for OriginalFunctionName.
3. in backend compiler, we build symbol table entry for OriginalFunctionName and pointer to the same symbol of PromotedFunctionName, so that ICP can find the correct target to promote.
Reviewers: mehdi_amini, tejohnson
Reviewed By: tejohnson
Subscribers: llvm-commits, Prazek
Differential Revision: https://reviews.llvm.org/D30754
llvm-svn: 297757
2017-03-14 18:33:01 +01:00
|
|
|
/// Return the GUID for \p OriginalId in the OidGuidMap.
|
|
|
|
GlobalValue::GUID getGUIDFromOriginalID(GlobalValue::GUID OriginalID) const {
|
|
|
|
const auto I = OidGuidMap.find(OriginalID);
|
|
|
|
return I == OidGuidMap.end() ? 0 : I->second;
|
|
|
|
}
|
|
|
|
|
2017-06-16 02:18:29 +02:00
|
|
|
std::set<std::string> &cfiFunctionDefs() { return CfiFunctionDefs; }
|
|
|
|
const std::set<std::string> &cfiFunctionDefs() const { return CfiFunctionDefs; }
|
|
|
|
|
|
|
|
std::set<std::string> &cfiFunctionDecls() { return CfiFunctionDecls; }
|
|
|
|
const std::set<std::string> &cfiFunctionDecls() const { return CfiFunctionDecls; }
|
|
|
|
|
2018-06-26 02:20:49 +02:00
|
|
|
/// Add a global value summary for a value.
|
|
|
|
void addGlobalValueSummary(const GlobalValue &GV,
|
|
|
|
std::unique_ptr<GlobalValueSummary> Summary) {
|
|
|
|
addGlobalValueSummary(getOrInsertValueInfo(&GV), std::move(Summary));
|
|
|
|
}
|
|
|
|
|
2016-04-24 16:57:11 +02:00
|
|
|
/// Add a global value summary for a value of the given name.
|
|
|
|
void addGlobalValueSummary(StringRef ValueName,
|
|
|
|
std::unique_ptr<GlobalValueSummary> Summary) {
|
2017-05-04 20:03:25 +02:00
|
|
|
addGlobalValueSummary(getOrInsertValueInfo(GlobalValue::getGUID(ValueName)),
|
|
|
|
std::move(Summary));
|
2016-03-14 22:18:10 +01:00
|
|
|
}
|
|
|
|
|
2017-05-04 20:03:25 +02:00
|
|
|
/// Add a global value summary for the given ValueInfo.
|
|
|
|
void addGlobalValueSummary(ValueInfo VI,
|
2016-04-24 16:57:11 +02:00
|
|
|
std::unique_ptr<GlobalValueSummary> Summary) {
|
2017-05-04 20:03:25 +02:00
|
|
|
addOriginalName(VI.getGUID(), Summary->getOriginalName());
|
|
|
|
// Here we have a notionally const VI, but the value it points to is owned
|
|
|
|
// by the non-const *this.
|
2018-01-22 14:35:40 +01:00
|
|
|
const_cast<GlobalValueSummaryMapTy::value_type *>(VI.getRef())
|
2017-05-04 20:03:25 +02:00
|
|
|
->second.SummaryList.push_back(std::move(Summary));
|
2016-03-14 22:18:10 +01:00
|
|
|
}
|
|
|
|
|
SamplePGO ThinLTO ICP fix for local functions.
Summary:
In SamplePGO, if the profile is collected from non-LTO binary, and used to drive ThinLTO, the indirect call promotion may fail because ThinLTO adjusts local function names to avoid conflicts. There are two places of where the mismatch can happen:
1. thin-link prepends SourceFileName to front of FuncName to build the GUID (GlobalValue::getGlobalIdentifier). Unlike instrumentation FDO, SamplePGO does not use the PGOFuncName scheme and therefore the indirect call target profile data contains a hash of the OriginalName.
2. backend compiler promotes some local functions to global and appends .llvm.{$ModuleHash} to the end of the FuncName to derive PromotedFunctionName
This patch tries at the best effort to find the GUID from the original local function name (in profile), and use that in ICP promotion, and in SamplePGO matching that happens in the backend after importing/inlining:
1. in thin-link, it builds the map from OriginalName to GUID so that when thin-link reads in indirect call target profile (represented by OriginalName), it knows which GUID to import.
2. in backend compiler, if sample profile reader cannot find a profile match for PromotedFunctionName, it will try to find if there is a match for OriginalFunctionName.
3. in backend compiler, we build symbol table entry for OriginalFunctionName and pointer to the same symbol of PromotedFunctionName, so that ICP can find the correct target to promote.
Reviewers: mehdi_amini, tejohnson
Reviewed By: tejohnson
Subscribers: llvm-commits, Prazek
Differential Revision: https://reviews.llvm.org/D30754
llvm-svn: 297757
2017-03-14 18:33:01 +01:00
|
|
|
/// Add an original name for the value of the given GUID.
|
|
|
|
void addOriginalName(GlobalValue::GUID ValueGUID,
|
|
|
|
GlobalValue::GUID OrigGUID) {
|
|
|
|
if (OrigGUID == 0 || ValueGUID == OrigGUID)
|
|
|
|
return;
|
|
|
|
if (OidGuidMap.count(OrigGUID) && OidGuidMap[OrigGUID] != ValueGUID)
|
|
|
|
OidGuidMap[OrigGUID] = 0;
|
|
|
|
else
|
|
|
|
OidGuidMap[OrigGUID] = ValueGUID;
|
|
|
|
}
|
|
|
|
|
[ThinLTO] Restructure AliasSummary to contain ValueInfo of Aliasee
Summary:
The AliasSummary previously contained the AliaseeGUID, which was only
populated when reading the summary from bitcode. This patch changes it
to instead hold the ValueInfo of the aliasee, and always populates it.
This enables more efficient access to the ValueInfo (specifically in the
recent patch r352438 which needed to perform an index hash table lookup
using the aliasee GUID).
As noted in the comments in AliasSummary, we no longer technically need
to keep a pointer to the corresponding aliasee summary, since it could
be obtained by walking the list of summaries on the ValueInfo looking
for the summary in the same module. However, I am concerned that this
would be inefficient when walking through the index during the thin
link for various analyses. That can be reevaluated in the future.
By always populating this new field, we can remove the guard and special
handling for a 0 aliasee GUID when dumping the dot graph of the summary.
An additional improvement in this patch is when reading the summaries
from LLVM assembly we now set the AliaseeSummary field to the aliasee
summary in that same module, which makes it consistent with the behavior
when reading the summary from bitcode.
Reviewers: pcc, mehdi_amini
Subscribers: inglorion, eraman, steven_wu, dexonsmith, arphaman, llvm-commits
Differential Revision: https://reviews.llvm.org/D57470
llvm-svn: 356268
2019-03-15 16:11:38 +01:00
|
|
|
/// Find the summary for ValueInfo \p VI in module \p ModuleId, or nullptr if
|
2016-04-27 15:28:35 +02:00
|
|
|
/// not found.
|
[ThinLTO] Restructure AliasSummary to contain ValueInfo of Aliasee
Summary:
The AliasSummary previously contained the AliaseeGUID, which was only
populated when reading the summary from bitcode. This patch changes it
to instead hold the ValueInfo of the aliasee, and always populates it.
This enables more efficient access to the ValueInfo (specifically in the
recent patch r352438 which needed to perform an index hash table lookup
using the aliasee GUID).
As noted in the comments in AliasSummary, we no longer technically need
to keep a pointer to the corresponding aliasee summary, since it could
be obtained by walking the list of summaries on the ValueInfo looking
for the summary in the same module. However, I am concerned that this
would be inefficient when walking through the index during the thin
link for various analyses. That can be reevaluated in the future.
By always populating this new field, we can remove the guard and special
handling for a 0 aliasee GUID when dumping the dot graph of the summary.
An additional improvement in this patch is when reading the summaries
from LLVM assembly we now set the AliaseeSummary field to the aliasee
summary in that same module, which makes it consistent with the behavior
when reading the summary from bitcode.
Reviewers: pcc, mehdi_amini
Subscribers: inglorion, eraman, steven_wu, dexonsmith, arphaman, llvm-commits
Differential Revision: https://reviews.llvm.org/D57470
llvm-svn: 356268
2019-03-15 16:11:38 +01:00
|
|
|
GlobalValueSummary *findSummaryInModule(ValueInfo VI, StringRef ModuleId) const {
|
|
|
|
auto SummaryList = VI.getSummaryList();
|
2016-04-27 15:28:35 +02:00
|
|
|
auto Summary =
|
[ThinLTO] Restructure AliasSummary to contain ValueInfo of Aliasee
Summary:
The AliasSummary previously contained the AliaseeGUID, which was only
populated when reading the summary from bitcode. This patch changes it
to instead hold the ValueInfo of the aliasee, and always populates it.
This enables more efficient access to the ValueInfo (specifically in the
recent patch r352438 which needed to perform an index hash table lookup
using the aliasee GUID).
As noted in the comments in AliasSummary, we no longer technically need
to keep a pointer to the corresponding aliasee summary, since it could
be obtained by walking the list of summaries on the ValueInfo looking
for the summary in the same module. However, I am concerned that this
would be inefficient when walking through the index during the thin
link for various analyses. That can be reevaluated in the future.
By always populating this new field, we can remove the guard and special
handling for a 0 aliasee GUID when dumping the dot graph of the summary.
An additional improvement in this patch is when reading the summaries
from LLVM assembly we now set the AliaseeSummary field to the aliasee
summary in that same module, which makes it consistent with the behavior
when reading the summary from bitcode.
Reviewers: pcc, mehdi_amini
Subscribers: inglorion, eraman, steven_wu, dexonsmith, arphaman, llvm-commits
Differential Revision: https://reviews.llvm.org/D57470
llvm-svn: 356268
2019-03-15 16:11:38 +01:00
|
|
|
llvm::find_if(SummaryList,
|
2016-04-27 15:28:35 +02:00
|
|
|
[&](const std::unique_ptr<GlobalValueSummary> &Summary) {
|
|
|
|
return Summary->modulePath() == ModuleId;
|
|
|
|
});
|
[ThinLTO] Restructure AliasSummary to contain ValueInfo of Aliasee
Summary:
The AliasSummary previously contained the AliaseeGUID, which was only
populated when reading the summary from bitcode. This patch changes it
to instead hold the ValueInfo of the aliasee, and always populates it.
This enables more efficient access to the ValueInfo (specifically in the
recent patch r352438 which needed to perform an index hash table lookup
using the aliasee GUID).
As noted in the comments in AliasSummary, we no longer technically need
to keep a pointer to the corresponding aliasee summary, since it could
be obtained by walking the list of summaries on the ValueInfo looking
for the summary in the same module. However, I am concerned that this
would be inefficient when walking through the index during the thin
link for various analyses. That can be reevaluated in the future.
By always populating this new field, we can remove the guard and special
handling for a 0 aliasee GUID when dumping the dot graph of the summary.
An additional improvement in this patch is when reading the summaries
from LLVM assembly we now set the AliaseeSummary field to the aliasee
summary in that same module, which makes it consistent with the behavior
when reading the summary from bitcode.
Reviewers: pcc, mehdi_amini
Subscribers: inglorion, eraman, steven_wu, dexonsmith, arphaman, llvm-commits
Differential Revision: https://reviews.llvm.org/D57470
llvm-svn: 356268
2019-03-15 16:11:38 +01:00
|
|
|
if (Summary == SummaryList.end())
|
2016-04-27 15:28:35 +02:00
|
|
|
return nullptr;
|
|
|
|
return Summary->get();
|
|
|
|
}
|
|
|
|
|
[ThinLTO] Restructure AliasSummary to contain ValueInfo of Aliasee
Summary:
The AliasSummary previously contained the AliaseeGUID, which was only
populated when reading the summary from bitcode. This patch changes it
to instead hold the ValueInfo of the aliasee, and always populates it.
This enables more efficient access to the ValueInfo (specifically in the
recent patch r352438 which needed to perform an index hash table lookup
using the aliasee GUID).
As noted in the comments in AliasSummary, we no longer technically need
to keep a pointer to the corresponding aliasee summary, since it could
be obtained by walking the list of summaries on the ValueInfo looking
for the summary in the same module. However, I am concerned that this
would be inefficient when walking through the index during the thin
link for various analyses. That can be reevaluated in the future.
By always populating this new field, we can remove the guard and special
handling for a 0 aliasee GUID when dumping the dot graph of the summary.
An additional improvement in this patch is when reading the summaries
from LLVM assembly we now set the AliaseeSummary field to the aliasee
summary in that same module, which makes it consistent with the behavior
when reading the summary from bitcode.
Reviewers: pcc, mehdi_amini
Subscribers: inglorion, eraman, steven_wu, dexonsmith, arphaman, llvm-commits
Differential Revision: https://reviews.llvm.org/D57470
llvm-svn: 356268
2019-03-15 16:11:38 +01:00
|
|
|
/// Find the summary for global \p GUID in module \p ModuleId, or nullptr if
|
|
|
|
/// not found.
|
|
|
|
GlobalValueSummary *findSummaryInModule(GlobalValue::GUID ValueGUID,
|
|
|
|
StringRef ModuleId) const {
|
|
|
|
auto CalleeInfo = getValueInfo(ValueGUID);
|
|
|
|
if (!CalleeInfo)
|
|
|
|
return nullptr; // This function does not have a summary
|
|
|
|
return findSummaryInModule(CalleeInfo, ModuleId);
|
|
|
|
}
|
|
|
|
|
2016-04-24 16:57:11 +02:00
|
|
|
/// Returns the first GlobalValueSummary for \p GV, asserting that there
|
2016-04-05 02:40:16 +02:00
|
|
|
/// is only one if \p PerModuleIndex.
|
2016-04-24 16:57:11 +02:00
|
|
|
GlobalValueSummary *getGlobalValueSummary(const GlobalValue &GV,
|
|
|
|
bool PerModuleIndex = true) const {
|
|
|
|
assert(GV.hasName() && "Can't get GlobalValueSummary for GV with no name");
|
2018-06-26 02:20:49 +02:00
|
|
|
return getGlobalValueSummary(GV.getGUID(), PerModuleIndex);
|
2016-04-05 02:40:16 +02:00
|
|
|
}
|
|
|
|
|
2016-04-24 16:57:11 +02:00
|
|
|
/// Returns the first GlobalValueSummary for \p ValueGUID, asserting that
|
|
|
|
/// there
|
2016-04-05 02:40:16 +02:00
|
|
|
/// is only one if \p PerModuleIndex.
|
2016-04-24 16:57:11 +02:00
|
|
|
GlobalValueSummary *getGlobalValueSummary(GlobalValue::GUID ValueGUID,
|
|
|
|
bool PerModuleIndex = true) const;
|
2016-04-05 02:40:16 +02:00
|
|
|
|
2016-04-01 07:33:11 +02:00
|
|
|
/// Table of modules, containing module hash and id.
|
|
|
|
const StringMap<std::pair<uint64_t, ModuleHash>> &modulePaths() const {
|
2016-03-26 04:35:38 +01:00
|
|
|
return ModulePathStringTable;
|
2016-03-14 22:18:10 +01:00
|
|
|
}
|
|
|
|
|
2016-04-01 07:33:11 +02:00
|
|
|
/// Table of modules, containing hash and id.
|
|
|
|
StringMap<std::pair<uint64_t, ModuleHash>> &modulePaths() {
|
|
|
|
return ModulePathStringTable;
|
|
|
|
}
|
2016-03-26 04:35:38 +01:00
|
|
|
|
2016-03-14 22:18:10 +01:00
|
|
|
/// Get the module ID recorded for the given module path.
|
|
|
|
uint64_t getModuleId(const StringRef ModPath) const {
|
2016-04-01 07:33:11 +02:00
|
|
|
return ModulePathStringTable.lookup(ModPath).first;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get the module SHA1 hash recorded for the given module path.
|
|
|
|
const ModuleHash &getModuleHash(const StringRef ModPath) const {
|
|
|
|
auto It = ModulePathStringTable.find(ModPath);
|
|
|
|
assert(It != ModulePathStringTable.end() && "Module not registered");
|
|
|
|
return It->second.second;
|
2016-03-14 22:18:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Convenience method for creating a promoted global name
|
|
|
|
/// for the given value name of a local, and its original module's ID.
|
2016-04-12 01:26:46 +02:00
|
|
|
static std::string getGlobalNameForLocal(StringRef Name, ModuleHash ModHash) {
|
2016-03-14 22:18:10 +01:00
|
|
|
SmallString<256> NewName(Name);
|
|
|
|
NewName += ".llvm.";
|
2017-10-31 13:56:09 +01:00
|
|
|
NewName += utostr((uint64_t(ModHash[0]) << 32) |
|
|
|
|
ModHash[1]); // Take the first 64 bits
|
2016-03-14 22:18:10 +01:00
|
|
|
return NewName.str();
|
|
|
|
}
|
|
|
|
|
2016-05-24 19:24:25 +02:00
|
|
|
/// Helper to obtain the unpromoted name for a global value (or the original
|
|
|
|
/// name if not promoted).
|
|
|
|
static StringRef getOriginalNameBeforePromote(StringRef Name) {
|
|
|
|
std::pair<StringRef, StringRef> Pair = Name.split(".llvm.");
|
|
|
|
return Pair.first;
|
|
|
|
}
|
|
|
|
|
2017-06-15 00:35:27 +02:00
|
|
|
typedef ModulePathStringTableTy::value_type ModuleInfo;
|
|
|
|
|
|
|
|
/// Add a new module with the given \p Hash, mapped to the given \p
|
|
|
|
/// ModID, and return a reference to the module.
|
|
|
|
ModuleInfo *addModule(StringRef ModPath, uint64_t ModId,
|
|
|
|
ModuleHash Hash = ModuleHash{{0}}) {
|
|
|
|
return &*ModulePathStringTable.insert({ModPath, {ModId, Hash}}).first;
|
2016-03-14 22:18:10 +01:00
|
|
|
}
|
|
|
|
|
2018-06-26 03:32:58 +02:00
|
|
|
/// Return module entry for module with the given \p ModPath.
|
|
|
|
ModuleInfo *getModule(StringRef ModPath) {
|
|
|
|
auto It = ModulePathStringTable.find(ModPath);
|
|
|
|
assert(It != ModulePathStringTable.end() && "Module not registered");
|
|
|
|
return &*It;
|
|
|
|
}
|
|
|
|
|
2016-03-14 22:18:10 +01:00
|
|
|
/// Check if the given Module has any functions available for exporting
|
|
|
|
/// in the index. We consider any module present in the ModulePathStringTable
|
|
|
|
/// to have exported functions.
|
|
|
|
bool hasExportedFunctions(const Module &M) const {
|
|
|
|
return ModulePathStringTable.count(M.getModuleIdentifier());
|
|
|
|
}
|
|
|
|
|
[ThinLTO] Efficiency fix for writing type id records in per-module indexes
Summary:
In D49565/r337503, the type id record writing was fixed so that only
referenced type ids were emitted into each per-module index for ThinLTO
distributed builds. However, this still left an efficiency issue: each
per-module index checked all type ids for membership in the referenced
set, yielding O(M*N) performance (M indexes and N type ids).
Change the TypeIdMap in the summary to be indexed by GUID, to facilitate
correlating with type identifier GUIDs referenced in the function
summary TypeIdInfo structures. This allowed simplifying other
places where a map from type id GUID to type id map entry was previously
being used to aid this correlation.
Also fix AsmWriter code to handle the rare case of type id GUID
collision.
For a large internal application, this reduced the thin link time by
almost 15%.
Reviewers: pcc, vitalybuka
Subscribers: mehdi_amini, inglorion, steven_wu, dexonsmith, llvm-commits
Differential Revision: https://reviews.llvm.org/D51330
llvm-svn: 343021
2018-09-25 22:14:40 +02:00
|
|
|
const TypeIdSummaryMapTy &typeIds() const { return TypeIdMap; }
|
2017-03-10 22:35:17 +01:00
|
|
|
|
[ThinLTO] Efficiency fix for writing type id records in per-module indexes
Summary:
In D49565/r337503, the type id record writing was fixed so that only
referenced type ids were emitted into each per-module index for ThinLTO
distributed builds. However, this still left an efficiency issue: each
per-module index checked all type ids for membership in the referenced
set, yielding O(M*N) performance (M indexes and N type ids).
Change the TypeIdMap in the summary to be indexed by GUID, to facilitate
correlating with type identifier GUIDs referenced in the function
summary TypeIdInfo structures. This allowed simplifying other
places where a map from type id GUID to type id map entry was previously
being used to aid this correlation.
Also fix AsmWriter code to handle the rare case of type id GUID
collision.
For a large internal application, this reduced the thin link time by
almost 15%.
Reviewers: pcc, vitalybuka
Subscribers: mehdi_amini, inglorion, steven_wu, dexonsmith, llvm-commits
Differential Revision: https://reviews.llvm.org/D51330
llvm-svn: 343021
2018-09-25 22:14:40 +02:00
|
|
|
/// Return an existing or new TypeIdSummary entry for \p TypeId.
|
|
|
|
/// This accessor can mutate the map and therefore should not be used in
|
|
|
|
/// the ThinLTO backends.
|
2017-03-22 19:04:39 +01:00
|
|
|
TypeIdSummary &getOrInsertTypeIdSummary(StringRef TypeId) {
|
[ThinLTO] Efficiency fix for writing type id records in per-module indexes
Summary:
In D49565/r337503, the type id record writing was fixed so that only
referenced type ids were emitted into each per-module index for ThinLTO
distributed builds. However, this still left an efficiency issue: each
per-module index checked all type ids for membership in the referenced
set, yielding O(M*N) performance (M indexes and N type ids).
Change the TypeIdMap in the summary to be indexed by GUID, to facilitate
correlating with type identifier GUIDs referenced in the function
summary TypeIdInfo structures. This allowed simplifying other
places where a map from type id GUID to type id map entry was previously
being used to aid this correlation.
Also fix AsmWriter code to handle the rare case of type id GUID
collision.
For a large internal application, this reduced the thin link time by
almost 15%.
Reviewers: pcc, vitalybuka
Subscribers: mehdi_amini, inglorion, steven_wu, dexonsmith, llvm-commits
Differential Revision: https://reviews.llvm.org/D51330
llvm-svn: 343021
2018-09-25 22:14:40 +02:00
|
|
|
auto TidIter = TypeIdMap.equal_range(GlobalValue::getGUID(TypeId));
|
|
|
|
for (auto It = TidIter.first; It != TidIter.second; ++It)
|
|
|
|
if (It->second.first == TypeId)
|
|
|
|
return It->second.second;
|
|
|
|
auto It = TypeIdMap.insert(
|
|
|
|
{GlobalValue::getGUID(TypeId), {TypeId, TypeIdSummary()}});
|
|
|
|
return It->second.second;
|
2017-01-19 02:20:11 +01:00
|
|
|
}
|
|
|
|
|
2017-03-22 19:04:39 +01:00
|
|
|
/// This returns either a pointer to the type id summary (if present in the
|
|
|
|
/// summary map) or null (if not present). This may be used when importing.
|
|
|
|
const TypeIdSummary *getTypeIdSummary(StringRef TypeId) const {
|
[ThinLTO] Efficiency fix for writing type id records in per-module indexes
Summary:
In D49565/r337503, the type id record writing was fixed so that only
referenced type ids were emitted into each per-module index for ThinLTO
distributed builds. However, this still left an efficiency issue: each
per-module index checked all type ids for membership in the referenced
set, yielding O(M*N) performance (M indexes and N type ids).
Change the TypeIdMap in the summary to be indexed by GUID, to facilitate
correlating with type identifier GUIDs referenced in the function
summary TypeIdInfo structures. This allowed simplifying other
places where a map from type id GUID to type id map entry was previously
being used to aid this correlation.
Also fix AsmWriter code to handle the rare case of type id GUID
collision.
For a large internal application, this reduced the thin link time by
almost 15%.
Reviewers: pcc, vitalybuka
Subscribers: mehdi_amini, inglorion, steven_wu, dexonsmith, llvm-commits
Differential Revision: https://reviews.llvm.org/D51330
llvm-svn: 343021
2018-09-25 22:14:40 +02:00
|
|
|
auto TidIter = TypeIdMap.equal_range(GlobalValue::getGUID(TypeId));
|
|
|
|
for (auto It = TidIter.first; It != TidIter.second; ++It)
|
|
|
|
if (It->second.first == TypeId)
|
|
|
|
return &It->second.second;
|
|
|
|
return nullptr;
|
2017-03-22 19:04:39 +01:00
|
|
|
}
|
|
|
|
|
2019-08-02 15:10:52 +02:00
|
|
|
TypeIdSummary *getTypeIdSummary(StringRef TypeId) {
|
|
|
|
return const_cast<TypeIdSummary *>(
|
|
|
|
static_cast<const ModuleSummaryIndex *>(this)->getTypeIdSummary(
|
|
|
|
TypeId));
|
|
|
|
}
|
|
|
|
|
[ThinLTO] Add summary entries for index-based WPD
Summary:
If LTOUnit splitting is disabled, the module summary analysis computes
the summary information necessary to perform single implementation
devirtualization during the thin link with the index and no IR. The
information collected from the regular LTO IR in the current hybrid WPD
algorithm is summarized, including:
1) For vtable definitions, record the function pointers and their offset
within the vtable initializer (subsumes the information collected from
IR by tryFindVirtualCallTargets).
2) A record for each type metadata summarizing the vtable definitions
decorated with that metadata (subsumes the TypeIdentiferMap collected
from IR).
Also added are the necessary bitcode records, and the corresponding
assembly support.
The follow-on index-based WPD patch is D55153.
Depends on D53890.
Reviewers: pcc
Subscribers: mehdi_amini, Prazek, inglorion, eraman, steven_wu, dexonsmith, arphaman, llvm-commits
Differential Revision: https://reviews.llvm.org/D54815
llvm-svn: 364960
2019-07-02 21:38:02 +02:00
|
|
|
const std::map<std::string, TypeIdCompatibleVtableInfo> &
|
|
|
|
typeIdCompatibleVtableMap() const {
|
|
|
|
return TypeIdCompatibleVtableMap;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return an existing or new TypeIdCompatibleVtableMap entry for \p TypeId.
|
|
|
|
/// This accessor can mutate the map and therefore should not be used in
|
|
|
|
/// the ThinLTO backends.
|
|
|
|
TypeIdCompatibleVtableInfo &
|
|
|
|
getOrInsertTypeIdCompatibleVtableSummary(StringRef TypeId) {
|
|
|
|
return TypeIdCompatibleVtableMap[TypeId];
|
|
|
|
}
|
|
|
|
|
|
|
|
/// For the given \p TypeId, this returns the TypeIdCompatibleVtableMap
|
|
|
|
/// entry if present in the summary map. This may be used when importing.
|
2019-07-03 17:12:38 +02:00
|
|
|
Optional<TypeIdCompatibleVtableInfo>
|
[ThinLTO] Add summary entries for index-based WPD
Summary:
If LTOUnit splitting is disabled, the module summary analysis computes
the summary information necessary to perform single implementation
devirtualization during the thin link with the index and no IR. The
information collected from the regular LTO IR in the current hybrid WPD
algorithm is summarized, including:
1) For vtable definitions, record the function pointers and their offset
within the vtable initializer (subsumes the information collected from
IR by tryFindVirtualCallTargets).
2) A record for each type metadata summarizing the vtable definitions
decorated with that metadata (subsumes the TypeIdentiferMap collected
from IR).
Also added are the necessary bitcode records, and the corresponding
assembly support.
The follow-on index-based WPD patch is D55153.
Depends on D53890.
Reviewers: pcc
Subscribers: mehdi_amini, Prazek, inglorion, eraman, steven_wu, dexonsmith, arphaman, llvm-commits
Differential Revision: https://reviews.llvm.org/D54815
llvm-svn: 364960
2019-07-02 21:38:02 +02:00
|
|
|
getTypeIdCompatibleVtableSummary(StringRef TypeId) const {
|
|
|
|
auto I = TypeIdCompatibleVtableMap.find(TypeId);
|
|
|
|
if (I == TypeIdCompatibleVtableMap.end())
|
|
|
|
return None;
|
|
|
|
return I->second;
|
|
|
|
}
|
|
|
|
|
2018-07-12 08:41:41 +02:00
|
|
|
/// Collect for the given module the list of functions it defines
|
2016-04-12 23:13:11 +02:00
|
|
|
/// (GUID -> Summary).
|
2016-04-25 23:09:51 +02:00
|
|
|
void collectDefinedFunctionsForModule(StringRef ModulePath,
|
|
|
|
GVSummaryMapTy &GVSummaryMap) const;
|
2016-04-16 09:02:16 +02:00
|
|
|
|
|
|
|
/// Collect for each module the list of Summaries it defines (GUID ->
|
|
|
|
/// Summary).
|
2019-02-26 08:38:21 +01:00
|
|
|
template <class Map>
|
|
|
|
void
|
|
|
|
collectDefinedGVSummariesPerModule(Map &ModuleToDefinedGVSummaries) const {
|
|
|
|
for (auto &GlobalList : *this) {
|
|
|
|
auto GUID = GlobalList.first;
|
|
|
|
for (auto &Summary : GlobalList.second.SummaryList) {
|
|
|
|
ModuleToDefinedGVSummaries[Summary->modulePath()][GUID] = Summary.get();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-01-22 14:35:40 +01:00
|
|
|
|
2018-05-26 04:34:13 +02:00
|
|
|
/// Print to an output stream.
|
|
|
|
void print(raw_ostream &OS, bool IsForDebug = false) const;
|
|
|
|
|
|
|
|
/// Dump to stderr (for debugging).
|
|
|
|
void dump() const;
|
|
|
|
|
2018-01-22 14:35:40 +01:00
|
|
|
/// Export summary to dot file for GraphViz.
|
|
|
|
void exportToDot(raw_ostream& OS) const;
|
2018-02-19 16:14:50 +01:00
|
|
|
|
|
|
|
/// Print out strongly connected components for debugging.
|
|
|
|
void dumpSCCs(raw_ostream &OS);
|
2018-11-16 08:08:00 +01:00
|
|
|
|
|
|
|
/// Analyze index and detect unmodified globals
|
2019-07-05 17:25:05 +02:00
|
|
|
void propagateAttributes(const DenseSet<GlobalValue::GUID> &PreservedSymbols);
|
2019-11-07 13:13:35 +01:00
|
|
|
|
|
|
|
/// Checks if we can import global variable from another module.
|
|
|
|
bool canImportGlobalVar(GlobalValueSummary *S, bool AnalyzeRefs) const;
|
2018-02-19 16:14:50 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/// GraphTraits definition to build SCC for the index
|
|
|
|
template <> struct GraphTraits<ValueInfo> {
|
|
|
|
typedef ValueInfo NodeRef;
|
2018-12-13 20:54:27 +01:00
|
|
|
using EdgeRef = FunctionSummary::EdgeTy &;
|
2018-02-19 16:14:50 +01:00
|
|
|
|
|
|
|
static NodeRef valueInfoFromEdge(FunctionSummary::EdgeTy &P) {
|
|
|
|
return P.first;
|
|
|
|
}
|
|
|
|
using ChildIteratorType =
|
|
|
|
mapped_iterator<std::vector<FunctionSummary::EdgeTy>::iterator,
|
|
|
|
decltype(&valueInfoFromEdge)>;
|
|
|
|
|
2018-12-13 20:54:27 +01:00
|
|
|
using ChildEdgeIteratorType = std::vector<FunctionSummary::EdgeTy>::iterator;
|
|
|
|
|
2018-02-19 16:14:50 +01:00
|
|
|
static NodeRef getEntryNode(ValueInfo V) { return V; }
|
|
|
|
|
|
|
|
static ChildIteratorType child_begin(NodeRef N) {
|
|
|
|
if (!N.getSummaryList().size()) // handle external function
|
|
|
|
return ChildIteratorType(
|
|
|
|
FunctionSummary::ExternalNode.CallGraphEdgeList.begin(),
|
|
|
|
&valueInfoFromEdge);
|
|
|
|
FunctionSummary *F =
|
|
|
|
cast<FunctionSummary>(N.getSummaryList().front()->getBaseObject());
|
|
|
|
return ChildIteratorType(F->CallGraphEdgeList.begin(), &valueInfoFromEdge);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ChildIteratorType child_end(NodeRef N) {
|
|
|
|
if (!N.getSummaryList().size()) // handle external function
|
|
|
|
return ChildIteratorType(
|
|
|
|
FunctionSummary::ExternalNode.CallGraphEdgeList.end(),
|
|
|
|
&valueInfoFromEdge);
|
|
|
|
FunctionSummary *F =
|
|
|
|
cast<FunctionSummary>(N.getSummaryList().front()->getBaseObject());
|
|
|
|
return ChildIteratorType(F->CallGraphEdgeList.end(), &valueInfoFromEdge);
|
|
|
|
}
|
2018-12-13 20:54:27 +01:00
|
|
|
|
|
|
|
static ChildEdgeIteratorType child_edge_begin(NodeRef N) {
|
|
|
|
if (!N.getSummaryList().size()) // handle external function
|
|
|
|
return FunctionSummary::ExternalNode.CallGraphEdgeList.begin();
|
|
|
|
|
|
|
|
FunctionSummary *F =
|
|
|
|
cast<FunctionSummary>(N.getSummaryList().front()->getBaseObject());
|
|
|
|
return F->CallGraphEdgeList.begin();
|
|
|
|
}
|
|
|
|
|
|
|
|
static ChildEdgeIteratorType child_edge_end(NodeRef N) {
|
|
|
|
if (!N.getSummaryList().size()) // handle external function
|
|
|
|
return FunctionSummary::ExternalNode.CallGraphEdgeList.end();
|
|
|
|
|
|
|
|
FunctionSummary *F =
|
|
|
|
cast<FunctionSummary>(N.getSummaryList().front()->getBaseObject());
|
|
|
|
return F->CallGraphEdgeList.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
static NodeRef edge_dest(EdgeRef E) { return E.first; }
|
2018-02-19 16:14:50 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct GraphTraits<ModuleSummaryIndex *> : public GraphTraits<ValueInfo> {
|
|
|
|
static NodeRef getEntryNode(ModuleSummaryIndex *I) {
|
|
|
|
std::unique_ptr<GlobalValueSummary> Root =
|
2019-08-15 17:54:37 +02:00
|
|
|
std::make_unique<FunctionSummary>(I->calculateCallGraphRoot());
|
2018-06-07 00:22:01 +02:00
|
|
|
GlobalValueSummaryInfo G(I->haveGVs());
|
2018-02-19 16:14:50 +01:00
|
|
|
G.SummaryList.push_back(std::move(Root));
|
|
|
|
static auto P =
|
|
|
|
GlobalValueSummaryMapTy::value_type(GlobalValue::GUID(0), std::move(G));
|
2018-06-07 00:22:01 +02:00
|
|
|
return ValueInfo(I->haveGVs(), &P);
|
2018-02-19 16:14:50 +01:00
|
|
|
}
|
2016-03-14 22:18:10 +01:00
|
|
|
};
|
2017-05-13 00:25:07 +02:00
|
|
|
} // end namespace llvm
|
2016-03-14 22:18:10 +01:00
|
|
|
|
2017-05-13 00:25:07 +02:00
|
|
|
#endif // LLVM_IR_MODULESUMMARYINDEX_H
|