Update prebuilt Clang to r416183b from Android.
https://android.googlesource.com/platform/prebuilts/clang/host/
linux-x86/+/06a71ddac05c22edb2d10b590e1769b3f8619bef
clang 12.0.5 (based on r416183b) from build 7284624.
Change-Id: I277a316abcf47307562d8b748b84870f31a72866
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/linux-x64/clang/include/llvm/IR/ModuleSummaryIndex.h b/linux-x64/clang/include/llvm/IR/ModuleSummaryIndex.h
index aacf8cf..d5a7ad6 100644
--- a/linux-x64/clang/include/llvm/IR/ModuleSummaryIndex.h
+++ b/linux-x64/clang/include/llvm/IR/ModuleSummaryIndex.h
@@ -23,12 +23,14 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/ScaledNumber.h"
#include "llvm/Support/StringSaver.h"
+#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <array>
#include <cassert>
@@ -119,7 +121,7 @@
using GlobalValueSummaryList = std::vector<std::unique_ptr<GlobalValueSummary>>;
-struct LLVM_ALIGNAS(8) GlobalValueSummaryInfo {
+struct alignas(8) GlobalValueSummaryInfo {
union NameOrGV {
NameOrGV(bool HaveGVs) {
if (HaveGVs)
@@ -172,7 +174,7 @@
RefAndFlags.setInt(HaveGVs);
}
- operator bool() const { return getRef(); }
+ explicit operator bool() const { return getRef(); }
GlobalValue::GUID getGUID() const { return getRef()->first; }
const GlobalValue *getValue() const {
@@ -547,6 +549,42 @@
// Indicate if the global value cannot be inlined.
unsigned NoInline : 1;
+ // Indicate if function should be always inlined.
+ unsigned AlwaysInline : 1;
+ };
+
+ /// Describes the uses of a parameter by the function.
+ struct ParamAccess {
+ static constexpr uint32_t RangeWidth = 64;
+
+ /// Describes the use of a value in a call instruction, specifying the
+ /// call's target, the value's parameter number, and the possible range of
+ /// offsets from the beginning of the value that are passed.
+ struct Call {
+ uint64_t ParamNo = 0;
+ ValueInfo Callee;
+ ConstantRange Offsets{/*BitWidth=*/RangeWidth, /*isFullSet=*/true};
+
+ Call() = default;
+ Call(uint64_t ParamNo, ValueInfo Callee, const ConstantRange &Offsets)
+ : ParamNo(ParamNo), Callee(Callee), Offsets(Offsets) {}
+ };
+
+ uint64_t ParamNo = 0;
+ /// The range contains byte offsets from the parameter pointer which
+ /// accessed by the function. In the per-module summary, it only includes
+ /// accesses made by the function instructions. In the combined summary, it
+ /// also includes accesses by nested function calls.
+ ConstantRange Use{/*BitWidth=*/RangeWidth, /*isFullSet=*/true};
+ /// In the per-module summary, it summarizes the byte offset applied to each
+ /// pointer parameter before passing to each corresponding callee.
+ /// In the combined summary, it's empty and information is propagated by
+ /// inter-procedural analysis and applied to the Use field.
+ std::vector<Call> Calls;
+
+ ParamAccess() = default;
+ ParamAccess(uint64_t ParamNo, const ConstantRange &Use)
+ : ParamNo(ParamNo), Use(Use) {}
};
/// Create an empty FunctionSummary (with specified call edges).
@@ -558,13 +596,14 @@
GlobalValue::LinkageTypes::AvailableExternallyLinkage,
/*NotEligibleToImport=*/true, /*Live=*/true, /*IsLocal=*/false,
/*CanAutoHide=*/false),
- /*InsCount=*/0, FunctionSummary::FFlags{}, /*EntryCount=*/0,
+ /*NumInsts=*/0, FunctionSummary::FFlags{}, /*EntryCount=*/0,
std::vector<ValueInfo>(), std::move(Edges),
std::vector<GlobalValue::GUID>(),
std::vector<FunctionSummary::VFuncId>(),
std::vector<FunctionSummary::VFuncId>(),
std::vector<FunctionSummary::ConstVCall>(),
- std::vector<FunctionSummary::ConstVCall>());
+ std::vector<FunctionSummary::ConstVCall>(),
+ std::vector<FunctionSummary::ParamAccess>());
}
/// A dummy node to reference external functions that aren't in the index
@@ -588,6 +627,10 @@
std::unique_ptr<TypeIdInfo> TIdInfo;
+ /// Uses for every parameter to this function.
+ using ParamAccessesTy = std::vector<ParamAccess>;
+ std::unique_ptr<ParamAccessesTy> ParamAccesses;
+
public:
FunctionSummary(GVFlags Flags, unsigned NumInsts, FFlags FunFlags,
uint64_t EntryCount, std::vector<ValueInfo> Refs,
@@ -596,18 +639,21 @@
std::vector<VFuncId> TypeTestAssumeVCalls,
std::vector<VFuncId> TypeCheckedLoadVCalls,
std::vector<ConstVCall> TypeTestAssumeConstVCalls,
- std::vector<ConstVCall> TypeCheckedLoadConstVCalls)
+ std::vector<ConstVCall> TypeCheckedLoadConstVCalls,
+ std::vector<ParamAccess> Params)
: GlobalValueSummary(FunctionKind, Flags, std::move(Refs)),
InstCount(NumInsts), FunFlags(FunFlags), EntryCount(EntryCount),
CallGraphEdgeList(std::move(CGEdges)) {
if (!TypeTests.empty() || !TypeTestAssumeVCalls.empty() ||
!TypeCheckedLoadVCalls.empty() || !TypeTestAssumeConstVCalls.empty() ||
!TypeCheckedLoadConstVCalls.empty())
- TIdInfo = llvm::make_unique<TypeIdInfo>(TypeIdInfo{
- std::move(TypeTests), std::move(TypeTestAssumeVCalls),
- std::move(TypeCheckedLoadVCalls),
- std::move(TypeTestAssumeConstVCalls),
- std::move(TypeCheckedLoadConstVCalls)});
+ TIdInfo = std::make_unique<TypeIdInfo>(
+ TypeIdInfo{std::move(TypeTests), std::move(TypeTestAssumeVCalls),
+ std::move(TypeCheckedLoadVCalls),
+ std::move(TypeTestAssumeConstVCalls),
+ std::move(TypeCheckedLoadConstVCalls)});
+ if (!Params.empty())
+ ParamAccesses = std::make_unique<ParamAccessesTy>(std::move(Params));
}
// Gets the number of readonly and writeonly refs in RefEdgeList
std::pair<unsigned, unsigned> specialRefCounts() const;
@@ -632,6 +678,8 @@
/// Return the list of <CalleeValueInfo, CalleeInfo> pairs.
ArrayRef<EdgeTy> calls() const { return CallGraphEdgeList; }
+ void addCall(EdgeTy E) { CallGraphEdgeList.push_back(E); }
+
/// 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.
@@ -676,11 +724,28 @@
return {};
}
+ /// Returns the list of known uses of pointer parameters.
+ ArrayRef<ParamAccess> paramAccesses() const {
+ if (ParamAccesses)
+ return *ParamAccesses;
+ return {};
+ }
+
+ /// Sets the list of known uses of pointer parameters.
+ void setParamAccesses(std::vector<ParamAccess> NewParams) {
+ if (NewParams.empty())
+ ParamAccesses.reset();
+ else if (ParamAccesses)
+ *ParamAccesses = std::move(NewParams);
+ else
+ ParamAccesses = std::make_unique<ParamAccessesTy>(std::move(NewParams));
+ }
+
/// 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)
- TIdInfo = llvm::make_unique<TypeIdInfo>();
+ TIdInfo = std::make_unique<TypeIdInfo>();
TIdInfo->TypeTests.push_back(Guid);
}
@@ -752,14 +817,33 @@
public:
struct GVarFlags {
- GVarFlags(bool ReadOnly, bool WriteOnly)
- : MaybeReadOnly(ReadOnly), MaybeWriteOnly(WriteOnly) {}
+ GVarFlags(bool ReadOnly, bool WriteOnly, bool Constant,
+ GlobalObject::VCallVisibility Vis)
+ : MaybeReadOnly(ReadOnly), MaybeWriteOnly(WriteOnly),
+ Constant(Constant), VCallVisibility(Vis) {}
- // In permodule summaries both MaybeReadOnly and MaybeWriteOnly
- // bits are set, because attribute propagation occurs later on
- // thin link phase.
+ // If true indicates that this global variable might be accessed
+ // purely by non-volatile load instructions. This in turn means
+ // it can be internalized in source and destination modules during
+ // thin LTO import because it neither modified nor its address
+ // is taken.
unsigned MaybeReadOnly : 1;
+ // If true indicates that variable is possibly only written to, so
+ // its value isn't loaded and its address isn't taken anywhere.
+ // False, when 'Constant' attribute is set.
unsigned MaybeWriteOnly : 1;
+ // Indicates that value is a compile-time constant. Global variable
+ // can be 'Constant' while not being 'ReadOnly' on several occasions:
+ // - it is volatile, (e.g mapped device address)
+ // - its address is taken, meaning that unlike 'ReadOnly' vars we can't
+ // internalize it.
+ // Constant variables are always imported thus giving compiler an
+ // opportunity to make some extra optimizations. Readonly constants
+ // are also internalized.
+ unsigned Constant : 1;
+ // Set from metadata on vtable definitions during the module summary
+ // analysis.
+ unsigned VCallVisibility : 2;
} VarFlags;
GlobalVarSummary(GVFlags Flags, GVarFlags VarFlags,
@@ -777,10 +861,17 @@
void setWriteOnly(bool WO) { VarFlags.MaybeWriteOnly = WO; }
bool maybeReadOnly() const { return VarFlags.MaybeReadOnly; }
bool maybeWriteOnly() const { return VarFlags.MaybeWriteOnly; }
+ bool isConstant() const { return VarFlags.Constant; }
+ void setVCallVisibility(GlobalObject::VCallVisibility Vis) {
+ VarFlags.VCallVisibility = Vis;
+ }
+ GlobalObject::VCallVisibility getVCallVisibility() const {
+ return (GlobalObject::VCallVisibility)VarFlags.VCallVisibility;
+ }
void setVTableFuncs(VTableFuncList Funcs) {
assert(!VTableFuncs);
- VTableFuncs = llvm::make_unique<VTableFuncList>(std::move(Funcs));
+ VTableFuncs = std::make_unique<VTableFuncList>(std::move(Funcs));
}
ArrayRef<VirtFuncOffset> vTableFuncs() const {
@@ -802,7 +893,8 @@
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;
+ Unknown, ///< Unknown (analysis not performed, don't lower)
+ } TheKind = Unknown;
/// 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
@@ -928,7 +1020,8 @@
/// 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;
+ std::map<std::string, TypeIdCompatibleVtableInfo, std::less<>>
+ TypeIdCompatibleVtableMap;
/// Mapping from original ID to GUID. If original ID can map to multiple
/// GUIDs, it will be mapped to 0.
@@ -939,6 +1032,11 @@
/// considered live.
bool WithGlobalValueDeadStripping = false;
+ /// Indicates that summary-based attribute propagation has run and
+ /// GVarFlags::MaybeReadonly / GVarFlags::MaybeWriteonly are really
+ /// read/write only.
+ bool WithAttributePropagation = false;
+
/// Indicates that summary-based synthetic entry count propagation has run
bool HasSyntheticEntryCounts = false;
@@ -962,6 +1060,9 @@
// some were not. Set when the combined index is created during the thin link.
bool PartiallySplitLTOUnits = false;
+ /// True if some of the FunctionSummary contains a ParamAccess.
+ bool HasParamAccess = false;
+
std::set<std::string> CfiFunctionDefs;
std::set<std::string> CfiFunctionDecls;
@@ -970,6 +1071,10 @@
StringSaver Saver;
BumpPtrAllocator Alloc;
+ // The total number of basic blocks in the module in the per-module summary or
+ // the total number of basic blocks in the LTO unit in the combined index.
+ uint64_t BlockCount;
+
// YAML I/O support.
friend yaml::MappingTraits<ModuleSummaryIndex>;
@@ -982,11 +1087,30 @@
public:
// See HaveGVs variable comment.
ModuleSummaryIndex(bool HaveGVs, bool EnableSplitLTOUnit = false)
- : HaveGVs(HaveGVs), EnableSplitLTOUnit(EnableSplitLTOUnit), Saver(Alloc) {
+ : HaveGVs(HaveGVs), EnableSplitLTOUnit(EnableSplitLTOUnit), Saver(Alloc),
+ BlockCount(0) {}
+
+ // Current version for the module summary in bitcode files.
+ // The BitcodeSummaryVersion should be bumped whenever we introduce changes
+ // in the way some record are interpreted, like flags for instance.
+ // Note that incrementing this may require changes in both BitcodeReader.cpp
+ // and BitcodeWriter.cpp.
+ static constexpr uint64_t BitcodeSummaryVersion = 9;
+
+ // Regular LTO module name for ASM writer
+ static constexpr const char *getRegularLTOModuleName() {
+ return "[Regular LTO]";
}
bool haveGVs() const { return HaveGVs; }
+ uint64_t getFlags() const;
+ void setFlags(uint64_t Flags);
+
+ uint64_t getBlockCount() const { return BlockCount; }
+ void addBlockCount(uint64_t C) { BlockCount += C; }
+ void setBlockCount(uint64_t C) { BlockCount = C; }
+
gvsummary_iterator begin() { return GlobalValueMap.begin(); }
const_gvsummary_iterator begin() const { return GlobalValueMap.begin(); }
gvsummary_iterator end() { return GlobalValueMap.end(); }
@@ -1063,6 +1187,18 @@
WithGlobalValueDeadStripping = true;
}
+ 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();
+ }
+
bool hasSyntheticEntryCounts() const { return HasSyntheticEntryCounts; }
void setHasSyntheticEntryCounts() { HasSyntheticEntryCounts = true; }
@@ -1079,6 +1215,8 @@
bool partiallySplitLTOUnits() const { return PartiallySplitLTOUnits; }
void setPartiallySplitLTOUnits() { PartiallySplitLTOUnits = true; }
+ bool hasParamAccess() const { return HasParamAccess; }
+
bool isGlobalValueLive(const GlobalValueSummary *GVS) const {
return !WithGlobalValueDeadStripping || GVS->isLive();
}
@@ -1150,6 +1288,8 @@
/// Add a global value summary for the given ValueInfo.
void addGlobalValueSummary(ValueInfo VI,
std::unique_ptr<GlobalValueSummary> Summary) {
+ if (const FunctionSummary *FS = dyn_cast<FunctionSummary>(Summary.get()))
+ HasParamAccess |= !FS->paramAccesses().empty();
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.
@@ -1235,13 +1375,15 @@
NewName += ".llvm.";
NewName += utostr((uint64_t(ModHash[0]) << 32) |
ModHash[1]); // Take the first 64 bits
- return NewName.str();
+ return std::string(NewName.str());
}
/// Helper to obtain the unpromoted name for a global value (or the original
- /// name if not promoted).
+ /// name if not promoted). Split off the rightmost ".llvm.${hash}" suffix,
+ /// because it is possible in certain clients (not clang at the moment) for
+ /// two rounds of ThinLTO optimization and therefore promotion to occur.
static StringRef getOriginalNameBeforePromote(StringRef Name) {
- std::pair<StringRef, StringRef> Pair = Name.split(".llvm.");
+ std::pair<StringRef, StringRef> Pair = Name.rsplit(".llvm.");
return Pair.first;
}
@@ -1279,7 +1421,7 @@
if (It->second.first == TypeId)
return It->second.second;
auto It = TypeIdMap.insert(
- {GlobalValue::getGUID(TypeId), {TypeId, TypeIdSummary()}});
+ {GlobalValue::getGUID(TypeId), {std::string(TypeId), TypeIdSummary()}});
return It->second.second;
}
@@ -1293,8 +1435,13 @@
return nullptr;
}
- const std::map<std::string, TypeIdCompatibleVtableInfo> &
- typeIdCompatibleVtableMap() const {
+ TypeIdSummary *getTypeIdSummary(StringRef TypeId) {
+ return const_cast<TypeIdSummary *>(
+ static_cast<const ModuleSummaryIndex *>(this)->getTypeIdSummary(
+ TypeId));
+ }
+
+ const auto &typeIdCompatibleVtableMap() const {
return TypeIdCompatibleVtableMap;
}
@@ -1303,7 +1450,7 @@
/// the ThinLTO backends.
TypeIdCompatibleVtableInfo &
getOrInsertTypeIdCompatibleVtableSummary(StringRef TypeId) {
- return TypeIdCompatibleVtableMap[TypeId];
+ return TypeIdCompatibleVtableMap[std::string(TypeId)];
}
/// For the given \p TypeId, this returns the TypeIdCompatibleVtableMap
@@ -1341,13 +1488,18 @@
void dump() const;
/// Export summary to dot file for GraphViz.
- void exportToDot(raw_ostream& OS) const;
+ void
+ exportToDot(raw_ostream &OS,
+ const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols) const;
/// Print out strongly connected components for debugging.
void dumpSCCs(raw_ostream &OS);
/// Analyze index and detect unmodified globals
void propagateAttributes(const DenseSet<GlobalValue::GUID> &PreservedSymbols);
+
+ /// Checks if we can import global variable from another module.
+ bool canImportGlobalVar(GlobalValueSummary *S, bool AnalyzeRefs) const;
};
/// GraphTraits definition to build SCC for the index
@@ -1411,7 +1563,7 @@
struct GraphTraits<ModuleSummaryIndex *> : public GraphTraits<ValueInfo> {
static NodeRef getEntryNode(ModuleSummaryIndex *I) {
std::unique_ptr<GlobalValueSummary> Root =
- make_unique<FunctionSummary>(I->calculateCallGraphRoot());
+ std::make_unique<FunctionSummary>(I->calculateCallGraphRoot());
GlobalValueSummaryInfo G(I->haveGVs());
G.SummaryList.push_back(std::move(Root));
static auto P =
@@ -1419,15 +1571,6 @@
return ValueInfo(I->haveGVs(), &P);
}
};
-
-static inline bool canImportGlobalVar(GlobalValueSummary *S) {
- assert(isa<GlobalVarSummary>(S->getBaseObject()));
-
- // We don't import GV with references, because it can result
- // in promotion of local variables in the source module.
- return !GlobalValue::isInterposableLinkage(S->linkage()) &&
- !S->notEligibleToImport() && S->refs().empty();
-}
} // end namespace llvm
#endif // LLVM_IR_MODULESUMMARYINDEX_H