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/ProfileData/Coverage/CoverageMapping.h b/linux-x64/clang/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 11758ac..09f2167 100644
--- a/linux-x64/clang/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/linux-x64/clang/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -20,10 +20,10 @@
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/ProfileData/InstrProf.h"
+#include "llvm/Support/Alignment.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Endian.h"
@@ -54,7 +54,9 @@
no_data_found,
unsupported_version,
truncated,
- malformed
+ malformed,
+ decompression_failed,
+ invalid_or_missing_arch_specifier
};
const std::error_category &coveragemap_category();
@@ -88,6 +90,8 @@
/// A Counter is an abstract value that describes how to compute the
/// execution count for a region of code using the collected profile count data.
struct Counter {
+ /// The CounterExpression kind (Add or Subtract) is encoded in bit 0 next to
+ /// the CounterKind. This means CounterKind has to leave bit 0 free.
enum CounterKind { Zero, CounterValueReference, Expression };
static const unsigned EncodingTagBits = 2;
static const unsigned EncodingTagMask = 0x3;
@@ -217,10 +221,20 @@
/// A GapRegion is like a CodeRegion, but its count is only set as the
/// line execution count when its the only region in the line.
- GapRegion
+ GapRegion,
+
+ /// A BranchRegion represents leaf-level boolean expressions and is
+ /// associated with two counters, each representing the number of times the
+ /// expression evaluates to true or false.
+ BranchRegion
};
+ /// Primary Counter that is also used for Branch Regions (TrueCount).
Counter Count;
+
+ /// Secondary Counter used for Branch Regions (FalseCount).
+ Counter FalseCount;
+
unsigned FileID, ExpandedFileID;
unsigned LineStart, ColumnStart, LineEnd, ColumnEnd;
RegionKind Kind;
@@ -232,6 +246,15 @@
LineStart(LineStart), ColumnStart(ColumnStart), LineEnd(LineEnd),
ColumnEnd(ColumnEnd), Kind(Kind) {}
+ CounterMappingRegion(Counter Count, Counter FalseCount, unsigned FileID,
+ unsigned ExpandedFileID, unsigned LineStart,
+ unsigned ColumnStart, unsigned LineEnd,
+ unsigned ColumnEnd, RegionKind Kind)
+ : Count(Count), FalseCount(FalseCount), FileID(FileID),
+ ExpandedFileID(ExpandedFileID), LineStart(LineStart),
+ ColumnStart(ColumnStart), LineEnd(LineEnd), ColumnEnd(ColumnEnd),
+ Kind(Kind) {}
+
static CounterMappingRegion
makeRegion(Counter Count, unsigned FileID, unsigned LineStart,
unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
@@ -261,6 +284,14 @@
LineEnd, (1U << 31) | ColumnEnd, GapRegion);
}
+ static CounterMappingRegion
+ makeBranchRegion(Counter Count, Counter FalseCount, unsigned FileID,
+ unsigned LineStart, unsigned ColumnStart, unsigned LineEnd,
+ unsigned ColumnEnd) {
+ return CounterMappingRegion(Count, FalseCount, FileID, 0, LineStart,
+ ColumnStart, LineEnd, ColumnEnd, BranchRegion);
+ }
+
inline LineColPair startLoc() const {
return LineColPair(LineStart, ColumnStart);
}
@@ -271,9 +302,17 @@
/// Associates a source range with an execution count.
struct CountedRegion : public CounterMappingRegion {
uint64_t ExecutionCount;
+ uint64_t FalseExecutionCount;
+ bool Folded;
CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount)
- : CounterMappingRegion(R), ExecutionCount(ExecutionCount) {}
+ : CounterMappingRegion(R), ExecutionCount(ExecutionCount),
+ FalseExecutionCount(0), Folded(false) {}
+
+ CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount,
+ uint64_t FalseExecutionCount)
+ : CounterMappingRegion(R), ExecutionCount(ExecutionCount),
+ FalseExecutionCount(FalseExecutionCount), Folded(false) {}
};
/// A Counter mapping context is used to connect the counters, expressions
@@ -301,12 +340,19 @@
struct FunctionRecord {
/// Raw function name.
std::string Name;
- /// Associated files.
+ /// Mapping from FileID (i.e. vector index) to filename. Used to support
+ /// macro expansions within a function in which the macro and function are
+ /// defined in separate files.
+ ///
+ /// TODO: Uniquing filenames across all function records may be a performance
+ /// optimization.
std::vector<std::string> Filenames;
/// Regions in the function along with their counts.
std::vector<CountedRegion> CountedRegions;
+ /// Branch Regions in the function along with their counts.
+ std::vector<CountedRegion> CountedBranchRegions;
/// The number of times this function was executed.
- uint64_t ExecutionCount;
+ uint64_t ExecutionCount = 0;
FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames)
: Name(Name), Filenames(Filenames.begin(), Filenames.end()) {}
@@ -314,10 +360,19 @@
FunctionRecord(FunctionRecord &&FR) = default;
FunctionRecord &operator=(FunctionRecord &&) = default;
- void pushRegion(CounterMappingRegion Region, uint64_t Count) {
+ void pushRegion(CounterMappingRegion Region, uint64_t Count,
+ uint64_t FalseCount) {
+ if (Region.Kind == CounterMappingRegion::BranchRegion) {
+ CountedBranchRegions.emplace_back(Region, Count, FalseCount);
+ // If both counters are hard-coded to zero, then this region represents a
+ // constant-folded branch.
+ if (Region.Count.isZero() && Region.FalseCount.isZero())
+ CountedBranchRegions.back().Folded = true;
+ return;
+ }
if (CountedRegions.empty())
ExecutionCount = Count;
- CountedRegions.emplace_back(Region, Count);
+ CountedRegions.emplace_back(Region, Count, FalseCount);
}
};
@@ -396,7 +451,8 @@
IsRegionEntry(IsRegionEntry), IsGapRegion(false) {}
CoverageSegment(unsigned Line, unsigned Col, uint64_t Count,
- bool IsRegionEntry, bool IsGapRegion = false)
+ bool IsRegionEntry, bool IsGapRegion = false,
+ bool IsBranchRegion = false)
: Line(Line), Col(Col), Count(Count), HasCount(true),
IsRegionEntry(IsRegionEntry), IsGapRegion(IsGapRegion) {}
@@ -476,6 +532,7 @@
std::string Filename;
std::vector<CoverageSegment> Segments;
std::vector<ExpansionRecord> Expansions;
+ std::vector<CountedRegion> BranchRegions;
public:
CoverageData() = default;
@@ -499,6 +556,9 @@
/// Expansions that can be further processed.
ArrayRef<ExpansionRecord> getExpansions() const { return Expansions; }
+
+ /// Branches that can be further processed.
+ ArrayRef<CountedRegion> getBranches() const { return BranchRegions; }
};
/// The mapping of profile information to coverage data.
@@ -508,6 +568,7 @@
class CoverageMapping {
DenseMap<size_t, DenseSet<size_t>> RecordProvenance;
std::vector<FunctionRecord> Functions;
+ DenseMap<size_t, SmallVector<unsigned, 0>> FilenameHash2RecordIndices;
std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches;
CoverageMapping() = default;
@@ -516,6 +577,13 @@
Error loadFunctionRecord(const CoverageMappingRecord &Record,
IndexedInstrProfReader &ProfileReader);
+ /// Look up the indices for function records which are at least partially
+ /// defined in the specified file. This is guaranteed to return a superset of
+ /// such records: extra records not in the file may be included if there is
+ /// a hash collision on the filename. Clients must be robust to collisions.
+ ArrayRef<unsigned>
+ getImpreciseRecordIndicesForFilename(StringRef Filename) const;
+
public:
CoverageMapping(const CoverageMapping &) = delete;
CoverageMapping &operator=(const CoverageMapping &) = delete;
@@ -527,6 +595,7 @@
/// Load the coverage mapping from the given object files and profile. If
/// \p Arches is non-empty, it must specify an architecture for each object.
+ /// Ignores non-instrumented object files unless all are not instrumented.
static Expected<std::unique_ptr<CoverageMapping>>
load(ArrayRef<StringRef> ObjectFilenames, StringRef ProfileFilename,
ArrayRef<StringRef> Arches = None);
@@ -664,37 +733,107 @@
return make_range(Begin, End);
}
-// Profile coverage map has the following layout:
-// [CoverageMapFileHeader]
-// [ArrayStart]
-// [CovMapFunctionRecord]
-// [CovMapFunctionRecord]
-// ...
-// [ArrayEnd]
-// [Encoded Region Mapping Data]
+// Coverage mappping data (V2) has the following layout:
+// IPSK_covmap:
+// [CoverageMapFileHeader]
+// [ArrayStart]
+// [CovMapFunctionRecordV2]
+// [CovMapFunctionRecordV2]
+// ...
+// [ArrayEnd]
+// [Encoded Filenames and Region Mapping Data]
+//
+// Coverage mappping data (V3) has the following layout:
+// IPSK_covmap:
+// [CoverageMapFileHeader]
+// [Encoded Filenames]
+// IPSK_covfun:
+// [ArrayStart]
+// odr_name_1: [CovMapFunctionRecordV3]
+// odr_name_2: [CovMapFunctionRecordV3]
+// ...
+// [ArrayEnd]
+//
+// Both versions of the coverage mapping format encode the same information,
+// but the V3 format does so more compactly by taking advantage of linkonce_odr
+// semantics (it allows exactly 1 function record per name reference).
+
+/// This namespace defines accessors shared by different versions of coverage
+/// mapping records.
+namespace accessors {
+
+/// Return the structural hash associated with the function.
+template <class FuncRecordTy, support::endianness Endian>
+uint64_t getFuncHash(const FuncRecordTy *Record) {
+ return support::endian::byte_swap<uint64_t, Endian>(Record->FuncHash);
+}
+
+/// Return the coverage map data size for the function.
+template <class FuncRecordTy, support::endianness Endian>
+uint64_t getDataSize(const FuncRecordTy *Record) {
+ return support::endian::byte_swap<uint32_t, Endian>(Record->DataSize);
+}
+
+/// Return the function lookup key. The value is considered opaque.
+template <class FuncRecordTy, support::endianness Endian>
+uint64_t getFuncNameRef(const FuncRecordTy *Record) {
+ return support::endian::byte_swap<uint64_t, Endian>(Record->NameRef);
+}
+
+/// Return the PGO name of the function. Used for formats in which the name is
+/// a hash.
+template <class FuncRecordTy, support::endianness Endian>
+Error getFuncNameViaRef(const FuncRecordTy *Record,
+ InstrProfSymtab &ProfileNames, StringRef &FuncName) {
+ uint64_t NameRef = getFuncNameRef<FuncRecordTy, Endian>(Record);
+ FuncName = ProfileNames.getFuncName(NameRef);
+ return Error::success();
+}
+
+/// Read coverage mapping out-of-line, from \p MappingBuf. This is used when the
+/// coverage mapping is attached to the file header, instead of to the function
+/// record.
+template <class FuncRecordTy, support::endianness Endian>
+StringRef getCoverageMappingOutOfLine(const FuncRecordTy *Record,
+ const char *MappingBuf) {
+ return {MappingBuf, size_t(getDataSize<FuncRecordTy, Endian>(Record))};
+}
+
+/// Advance to the next out-of-line coverage mapping and its associated
+/// function record.
+template <class FuncRecordTy, support::endianness Endian>
+std::pair<const char *, const FuncRecordTy *>
+advanceByOneOutOfLine(const FuncRecordTy *Record, const char *MappingBuf) {
+ return {MappingBuf + getDataSize<FuncRecordTy, Endian>(Record), Record + 1};
+}
+
+} // end namespace accessors
+
LLVM_PACKED_START
-template <class IntPtrT> struct CovMapFunctionRecordV1 {
+template <class IntPtrT>
+struct CovMapFunctionRecordV1 {
+ using ThisT = CovMapFunctionRecordV1<IntPtrT>;
+
#define COVMAP_V1
#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
#include "llvm/ProfileData/InstrProfData.inc"
#undef COVMAP_V1
+ CovMapFunctionRecordV1() = delete;
- // Return the structural hash associated with the function.
template <support::endianness Endian> uint64_t getFuncHash() const {
- return support::endian::byte_swap<uint64_t, Endian>(FuncHash);
+ return accessors::getFuncHash<ThisT, Endian>(this);
}
- // Return the coverage map data size for the funciton.
- template <support::endianness Endian> uint32_t getDataSize() const {
- return support::endian::byte_swap<uint32_t, Endian>(DataSize);
+ template <support::endianness Endian> uint64_t getDataSize() const {
+ return accessors::getDataSize<ThisT, Endian>(this);
}
- // Return function lookup key. The value is consider opaque.
+ /// Return function lookup key. The value is consider opaque.
template <support::endianness Endian> IntPtrT getFuncNameRef() const {
return support::endian::byte_swap<IntPtrT, Endian>(NamePtr);
}
- // Return the PGO name of the function */
+ /// Return the PGO name of the function.
template <support::endianness Endian>
Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
IntPtrT NameRef = getFuncNameRef<Endian>();
@@ -704,33 +843,119 @@
return make_error<CoverageMapError>(coveragemap_error::malformed);
return Error::success();
}
+
+ template <support::endianness Endian>
+ std::pair<const char *, const ThisT *>
+ advanceByOne(const char *MappingBuf) const {
+ return accessors::advanceByOneOutOfLine<ThisT, Endian>(this, MappingBuf);
+ }
+
+ template <support::endianness Endian> uint64_t getFilenamesRef() const {
+ llvm_unreachable("V1 function format does not contain a filenames ref");
+ }
+
+ template <support::endianness Endian>
+ StringRef getCoverageMapping(const char *MappingBuf) const {
+ return accessors::getCoverageMappingOutOfLine<ThisT, Endian>(this,
+ MappingBuf);
+ }
};
-struct CovMapFunctionRecord {
+struct CovMapFunctionRecordV2 {
+ using ThisT = CovMapFunctionRecordV2;
+
+#define COVMAP_V2
#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
#include "llvm/ProfileData/InstrProfData.inc"
+#undef COVMAP_V2
+ CovMapFunctionRecordV2() = delete;
- // Return the structural hash associated with the function.
template <support::endianness Endian> uint64_t getFuncHash() const {
- return support::endian::byte_swap<uint64_t, Endian>(FuncHash);
+ return accessors::getFuncHash<ThisT, Endian>(this);
}
- // Return the coverage map data size for the funciton.
- template <support::endianness Endian> uint32_t getDataSize() const {
- return support::endian::byte_swap<uint32_t, Endian>(DataSize);
+ template <support::endianness Endian> uint64_t getDataSize() const {
+ return accessors::getDataSize<ThisT, Endian>(this);
}
- // Return function lookup key. The value is consider opaque.
template <support::endianness Endian> uint64_t getFuncNameRef() const {
- return support::endian::byte_swap<uint64_t, Endian>(NameRef);
+ return accessors::getFuncNameRef<ThisT, Endian>(this);
}
- // Return the PGO name of the function */
template <support::endianness Endian>
Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
- uint64_t NameRef = getFuncNameRef<Endian>();
- FuncName = ProfileNames.getFuncName(NameRef);
- return Error::success();
+ return accessors::getFuncNameViaRef<ThisT, Endian>(this, ProfileNames,
+ FuncName);
+ }
+
+ template <support::endianness Endian>
+ std::pair<const char *, const ThisT *>
+ advanceByOne(const char *MappingBuf) const {
+ return accessors::advanceByOneOutOfLine<ThisT, Endian>(this, MappingBuf);
+ }
+
+ template <support::endianness Endian> uint64_t getFilenamesRef() const {
+ llvm_unreachable("V2 function format does not contain a filenames ref");
+ }
+
+ template <support::endianness Endian>
+ StringRef getCoverageMapping(const char *MappingBuf) const {
+ return accessors::getCoverageMappingOutOfLine<ThisT, Endian>(this,
+ MappingBuf);
+ }
+};
+
+struct CovMapFunctionRecordV3 {
+ using ThisT = CovMapFunctionRecordV3;
+
+#define COVMAP_V3
+#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name;
+#include "llvm/ProfileData/InstrProfData.inc"
+#undef COVMAP_V3
+ CovMapFunctionRecordV3() = delete;
+
+ template <support::endianness Endian> uint64_t getFuncHash() const {
+ return accessors::getFuncHash<ThisT, Endian>(this);
+ }
+
+ template <support::endianness Endian> uint64_t getDataSize() const {
+ return accessors::getDataSize<ThisT, Endian>(this);
+ }
+
+ template <support::endianness Endian> uint64_t getFuncNameRef() const {
+ return accessors::getFuncNameRef<ThisT, Endian>(this);
+ }
+
+ template <support::endianness Endian>
+ Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
+ return accessors::getFuncNameViaRef<ThisT, Endian>(this, ProfileNames,
+ FuncName);
+ }
+
+ /// Get the filename set reference.
+ template <support::endianness Endian> uint64_t getFilenamesRef() const {
+ return support::endian::byte_swap<uint64_t, Endian>(FilenamesRef);
+ }
+
+ /// Read the inline coverage mapping. Ignore the buffer parameter, it is for
+ /// out-of-line coverage mapping data only.
+ template <support::endianness Endian>
+ StringRef getCoverageMapping(const char *) const {
+ return StringRef(&CoverageMapping, getDataSize<Endian>());
+ }
+
+ // Advance to the next inline coverage mapping and its associated function
+ // record. Ignore the out-of-line coverage mapping buffer.
+ template <support::endianness Endian>
+ std::pair<const char *, const CovMapFunctionRecordV3 *>
+ advanceByOne(const char *) const {
+ assert(isAddrAligned(Align(8), this) && "Function record not aligned");
+ const char *Next = ((const char *)this) + sizeof(CovMapFunctionRecordV3) -
+ sizeof(char) + getDataSize<Endian>();
+ // Each function record has an alignment of 8, so we need to adjust
+ // alignment before reading the next record.
+ Next += offsetToAlignedAddr(Next, Align(8));
+ return {nullptr, reinterpret_cast<const CovMapFunctionRecordV3 *>(Next)};
}
};
@@ -767,12 +992,26 @@
// A new interpretation of the columnEnd field is added in order to mark
// regions as gap areas.
Version3 = 2,
- // The current version is Version3
+ // Function records are named, uniqued, and moved to a dedicated section.
+ Version4 = 3,
+ // Branch regions referring to two counters are added
+ Version5 = 4,
+ // The current version is Version5.
CurrentVersion = INSTR_PROF_COVMAP_VERSION
};
template <int CovMapVersion, class IntPtrT> struct CovMapTraits {
- using CovMapFuncRecordType = CovMapFunctionRecord;
+ using CovMapFuncRecordType = CovMapFunctionRecordV3;
+ using NameRefType = uint64_t;
+};
+
+template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version3, IntPtrT> {
+ using CovMapFuncRecordType = CovMapFunctionRecordV2;
+ using NameRefType = uint64_t;
+};
+
+template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version2, IntPtrT> {
+ using CovMapFuncRecordType = CovMapFunctionRecordV2;
using NameRefType = uint64_t;
};