Update prebuilt Clang to r365631c1 from Android.
The version we had was segfaulting.
Bug: 132420445
Change-Id: Icb45a6fe0b4e2166f7895e669df1157cec9fb4e0
diff --git a/linux-x64/clang/include/llvm/ProfileData/Coverage/CoverageMappingReader.h b/linux-x64/clang/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
index dbb1976..57a2aae 100644
--- a/linux-x64/clang/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
+++ b/linux-x64/clang/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
@@ -203,9 +203,15 @@
BinaryCoverageReader(const BinaryCoverageReader &) = delete;
BinaryCoverageReader &operator=(const BinaryCoverageReader &) = delete;
+ static Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>>
+ create(MemoryBufferRef ObjectBuffer, StringRef Arch,
+ SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers);
+
static Expected<std::unique_ptr<BinaryCoverageReader>>
- create(std::unique_ptr<MemoryBuffer> &ObjectBuffer,
- StringRef Arch);
+ createCoverageReaderFromBuffer(StringRef Coverage,
+ InstrProfSymtab &&ProfileNames,
+ uint8_t BytesInAddress,
+ support::endianness Endian);
Error readNextRecord(CoverageMappingRecord &Record) override;
};
diff --git a/linux-x64/clang/include/llvm/ProfileData/GCOV.h b/linux-x64/clang/include/llvm/ProfileData/GCOV.h
index 27b76b5..004ff3f 100644
--- a/linux-x64/clang/include/llvm/ProfileData/GCOV.h
+++ b/linux-x64/clang/include/llvm/ProfileData/GCOV.h
@@ -44,9 +44,10 @@
/// A struct for passing gcov options between functions.
struct Options {
- Options(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N)
+ Options(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N, bool X)
: AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F),
- PreservePaths(P), UncondBranch(U), LongFileNames(L), NoOutput(N) {}
+ PreservePaths(P), UncondBranch(U), LongFileNames(L), NoOutput(N),
+ HashFilenames(X) {}
bool AllBlocks;
bool BranchInfo;
@@ -56,6 +57,7 @@
bool UncondBranch;
bool LongFileNames;
bool NoOutput;
+ bool HashFilenames;
};
} // end namespace GCOV
@@ -316,12 +318,6 @@
uint64_t Count = 0;
};
- struct SortDstEdgesFunctor {
- bool operator()(const GCOVEdge *E1, const GCOVEdge *E2) {
- return E1->Dst.Number < E2->Dst.Number;
- }
- };
-
public:
using EdgeIterator = SmallVectorImpl<GCOVEdge *>::const_iterator;
using BlockVector = SmallVector<const GCOVBlock *, 4>;
diff --git a/linux-x64/clang/include/llvm/ProfileData/InstrProf.h b/linux-x64/clang/include/llvm/ProfileData/InstrProf.h
index 9ea1b9b..c7d764a 100644
--- a/linux-x64/clang/include/llvm/ProfileData/InstrProf.h
+++ b/linux-x64/clang/include/llvm/ProfileData/InstrProf.h
@@ -234,7 +234,7 @@
bool canRenameComdatFunc(const Function &F, bool CheckAddressTaken = false);
enum InstrProfValueKind : uint32_t {
-#define VALUE_PROF_KIND(Enumerator, Value) Enumerator = Value,
+#define VALUE_PROF_KIND(Enumerator, Value, Descr) Enumerator = Value,
#include "llvm/ProfileData/InstrProfData.inc"
};
@@ -590,6 +590,70 @@
return PGOName.drop_front(S + 1);
}
+// To store the sums of profile count values, or the percentage of
+// the sums of the total count values.
+struct CountSumOrPercent {
+ uint64_t NumEntries;
+ double CountSum;
+ double ValueCounts[IPVK_Last - IPVK_First + 1];
+ CountSumOrPercent() : NumEntries(0), CountSum(0.0f), ValueCounts() {}
+ void reset() {
+ NumEntries = 0;
+ CountSum = 0.0f;
+ for (unsigned I = 0; I < IPVK_Last - IPVK_First + 1; I++)
+ ValueCounts[I] = 0.0f;
+ }
+};
+
+// Function level or program level overlap information.
+struct OverlapStats {
+ enum OverlapStatsLevel { ProgramLevel, FunctionLevel };
+ // Sum of the total count values for the base profile.
+ CountSumOrPercent Base;
+ // Sum of the total count values for the test profile.
+ CountSumOrPercent Test;
+ // Overlap lap score. Should be in range of [0.0f to 1.0f].
+ CountSumOrPercent Overlap;
+ CountSumOrPercent Mismatch;
+ CountSumOrPercent Unique;
+ OverlapStatsLevel Level;
+ const std::string *BaseFilename;
+ const std::string *TestFilename;
+ StringRef FuncName;
+ uint64_t FuncHash;
+ bool Valid;
+
+ OverlapStats(OverlapStatsLevel L = ProgramLevel)
+ : Level(L), BaseFilename(nullptr), TestFilename(nullptr), FuncHash(0),
+ Valid(false) {}
+
+ void dump(raw_fd_ostream &OS) const;
+
+ void setFuncInfo(StringRef Name, uint64_t Hash) {
+ FuncName = Name;
+ FuncHash = Hash;
+ }
+
+ Error accumuateCounts(const std::string &BaseFilename,
+ const std::string &TestFilename, bool IsCS);
+ void addOneMismatch(const CountSumOrPercent &MismatchFunc);
+ void addOneUnique(const CountSumOrPercent &UniqueFunc);
+
+ static inline double score(uint64_t Val1, uint64_t Val2, double Sum1,
+ double Sum2) {
+ if (Sum1 < 1.0f || Sum2 < 1.0f)
+ return 0.0f;
+ return std::min(Val1 / Sum1, Val2 / Sum2);
+ }
+};
+
+// This is used to filter the functions whose overlap information
+// to be output.
+struct OverlapFuncFilters {
+ uint64_t ValueCutoff;
+ const std::string NameFilter;
+};
+
struct InstrProfValueSiteRecord {
/// Value profiling data pairs at a given value site.
std::list<InstrProfValueData> ValueData;
@@ -615,6 +679,10 @@
function_ref<void(instrprof_error)> Warn);
/// Scale up value profile data counts.
void scale(uint64_t Weight, function_ref<void(instrprof_error)> Warn);
+
+ /// Compute the overlap b/w this record and Input record.
+ void overlap(InstrProfValueSiteRecord &Input, uint32_t ValueKind,
+ OverlapStats &Overlap, OverlapStats &FuncLevelOverlap);
};
/// Profiling information for a single function.
@@ -703,6 +771,18 @@
/// Clear value data entries
void clearValueData() { ValueData = nullptr; }
+ /// Compute the sums of all counts and store in Sum.
+ void accumuateCounts(CountSumOrPercent &Sum) const;
+
+ /// Compute the overlap b/w this IntrprofRecord and Other.
+ void overlap(InstrProfRecord &Other, OverlapStats &Overlap,
+ OverlapStats &FuncLevelOverlap, uint64_t ValueCutoff);
+
+ /// Compute the overlap of value profile counts.
+ void overlapValueProfData(uint32_t ValueKind, InstrProfRecord &Src,
+ OverlapStats &Overlap,
+ OverlapStats &FuncLevelOverlap);
+
private:
struct ValueProfData {
std::vector<InstrProfValueSiteRecord> IndirectCallSites;
@@ -767,10 +847,20 @@
StringRef Name;
uint64_t Hash;
+ // We reserve this bit as the flag for context sensitive profile record.
+ static const int CS_FLAG_IN_FUNC_HASH = 60;
+
NamedInstrProfRecord() = default;
NamedInstrProfRecord(StringRef Name, uint64_t Hash,
std::vector<uint64_t> Counts)
: InstrProfRecord(std::move(Counts)), Name(Name), Hash(Hash) {}
+
+ static bool hasCSFlagInHash(uint64_t FuncHash) {
+ return ((FuncHash >> CS_FLAG_IN_FUNC_HASH) & 1);
+ }
+ static void setCSFlagInHash(uint64_t &FuncHash) {
+ FuncHash |= ((uint64_t)1 << CS_FLAG_IN_FUNC_HASH);
+ }
};
uint32_t InstrProfRecord::getNumValueKinds() const {
@@ -1004,6 +1094,8 @@
// from control data struct is changed from raw pointer to Name's MD5 value.
// Version 4: ValueDataBegin and ValueDataSizes fields are removed from the
// raw header.
+// Version 5: Bit 60 of FuncHash is reserved for the flag for the context
+// sensitive records.
const uint64_t Version = INSTR_PROF_RAW_VERSION;
template <class IntPtrT> inline uint64_t getMagic();
@@ -1040,9 +1132,12 @@
void getMemOPSizeRangeFromOption(StringRef Str, int64_t &RangeStart,
int64_t &RangeLast);
+// Create a COMDAT variable INSTR_PROF_RAW_VERSION_VAR to make the runtime
+// aware this is an ir_level profile so it can set the version flag.
+void createIRLevelProfileFlagVar(Module &M, bool IsCS);
+
// Create the variable for the profile file name.
void createProfileFileNameVar(Module &M, StringRef InstrProfileOutput);
} // end namespace llvm
-
#endif // LLVM_PROFILEDATA_INSTRPROF_H
diff --git a/linux-x64/clang/include/llvm/ProfileData/InstrProfData.inc b/linux-x64/clang/include/llvm/ProfileData/InstrProfData.inc
index e1e2df5..749781b 100644
--- a/linux-x64/clang/include/llvm/ProfileData/InstrProfData.inc
+++ b/linux-x64/clang/include/llvm/ProfileData/InstrProfData.inc
@@ -169,7 +169,7 @@
/* VALUE_PROF_KIND start */
#ifndef VALUE_PROF_KIND
-#define VALUE_PROF_KIND(Enumerator, Value)
+#define VALUE_PROF_KIND(Enumerator, Value, Descr)
#else
#define INSTR_PROF_DATA_DEFINED
#endif
@@ -182,16 +182,16 @@
* For this remapping the ProfData is used. ProfData contains both the function
* name hash and the function address.
*/
-VALUE_PROF_KIND(IPVK_IndirectCallTarget, 0)
+VALUE_PROF_KIND(IPVK_IndirectCallTarget, 0, "indirect call target")
/* For memory intrinsic functions size profiling. */
-VALUE_PROF_KIND(IPVK_MemOPSize, 1)
+VALUE_PROF_KIND(IPVK_MemOPSize, 1, "memory intrinsic functions size")
/* These two kinds must be the last to be
* declared. This is to make sure the string
* array created with the template can be
* indexed with the kind value.
*/
-VALUE_PROF_KIND(IPVK_First, IPVK_IndirectCallTarget)
-VALUE_PROF_KIND(IPVK_Last, IPVK_MemOPSize)
+VALUE_PROF_KIND(IPVK_First, IPVK_IndirectCallTarget, "first")
+VALUE_PROF_KIND(IPVK_Last, IPVK_MemOPSize, "last")
#undef VALUE_PROF_KIND
/* VALUE_PROF_KIND end */
@@ -265,6 +265,9 @@
INSTR_PROF_SECT_ENTRY(IPSK_covmap, \
INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COMMON), \
INSTR_PROF_COVMAP_COFF, "__LLVM_COV,")
+INSTR_PROF_SECT_ENTRY(IPSK_orderfile, \
+ INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_COMMON), \
+ INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_COFF), "__DATA,")
#undef INSTR_PROF_SECT_ENTRY
#endif
@@ -635,10 +638,12 @@
* version for other variants of profile. We set the lowest bit of the upper 8
* bits (i.e. bit 56) to 1 to indicate if this is an IR-level instrumentaiton
* generated profile, and 0 if this is a Clang FE generated profile.
+ * 1 in bit 57 indicates there are context-sensitive records in the profile.
*/
#define VARIANT_MASKS_ALL 0xff00000000000000ULL
#define GET_VERSION(V) ((V) & ~VARIANT_MASKS_ALL)
#define VARIANT_MASK_IR_PROF (0x1ULL << 56)
+#define VARIANT_MASK_CSIR_PROF (0x1ULL << 57)
#define INSTR_PROF_RAW_VERSION_VAR __llvm_profile_raw_version
#define INSTR_PROF_PROFILE_RUNTIME_VAR __llvm_profile_runtime
@@ -654,6 +659,7 @@
#define INSTR_PROF_VALS_COMMON __llvm_prf_vals
#define INSTR_PROF_VNODES_COMMON __llvm_prf_vnds
#define INSTR_PROF_COVMAP_COMMON __llvm_covmap
+#define INSTR_PROF_ORDERFILE_COMMON __llvm_orderfile
/* Windows section names. Because these section names contain dollar characters,
* they must be quoted.
*/
@@ -663,6 +669,7 @@
#define INSTR_PROF_VALS_COFF ".lprfv$M"
#define INSTR_PROF_VNODES_COFF ".lprfnd$M"
#define INSTR_PROF_COVMAP_COFF ".lcovmap$M"
+#define INSTR_PROF_ORDERFILE_COFF ".lorderfile$M"
#ifdef _WIN32
/* Runtime section names and name strings. */
@@ -676,6 +683,7 @@
/* Value profile nodes section. */
#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_VNODES_COFF
#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_COVMAP_COFF
+#define INSTR_PROF_ORDERFILE_SECT_NAME INSTR_PROF_ORDERFILE_COFF
#else
/* Runtime section names and name strings. */
#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_DATA_COMMON)
@@ -688,8 +696,18 @@
/* Value profile nodes section. */
#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COMMON)
#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COMMON)
+/* Order file instrumentation. */
+#define INSTR_PROF_ORDERFILE_SECT_NAME \
+ INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_COMMON)
#endif
+#define INSTR_PROF_ORDERFILE_BUFFER_NAME _llvm_order_file_buffer
+#define INSTR_PROF_ORDERFILE_BUFFER_NAME_STR \
+ INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_BUFFER_NAME)
+#define INSTR_PROF_ORDERFILE_BUFFER_IDX_NAME _llvm_order_file_buffer_idx
+#define INSTR_PROF_ORDERFILE_BUFFER_IDX_NAME_STR \
+ INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_BUFFER_IDX_NAME)
+
/* Macros to define start/stop section symbol for a given
* section on Linux. For instance
* INSTR_PROF_SECT_START(INSTR_PROF_DATA_SECT_NAME) will
@@ -723,6 +741,12 @@
#endif /* INSTR_PROF_DATA_INC */
+#ifndef INSTR_ORDER_FILE_INC
+// The maximal # of functions: 128*1024 (the buffer size will be 128*4 KB).
+#define INSTR_ORDER_FILE_BUFFER_SIZE 131072
+#define INSTR_ORDER_FILE_BUFFER_BITS 17
+#define INSTR_ORDER_FILE_BUFFER_MASK 0x1ffff
+#endif /* INSTR_ORDER_FILE_INC */
#else
#undef INSTR_PROF_DATA_DEFINED
#endif
diff --git a/linux-x64/clang/include/llvm/ProfileData/InstrProfReader.h b/linux-x64/clang/include/llvm/ProfileData/InstrProfReader.h
index d465420..73751fa 100644
--- a/linux-x64/clang/include/llvm/ProfileData/InstrProfReader.h
+++ b/linux-x64/clang/include/llvm/ProfileData/InstrProfReader.h
@@ -77,6 +77,8 @@
virtual bool isIRLevelProfile() const = 0;
+ virtual bool hasCSIRLevelProfile() const = 0;
+
/// Return the PGO symtab. There are three different readers:
/// Raw, Text, and Indexed profile readers. The first two types
/// of readers are used only by llvm-profdata tool, while the indexed
@@ -89,6 +91,9 @@
/// compiler.
virtual InstrProfSymtab &getSymtab() = 0;
+ /// Compute the sum of counts and return in Sum.
+ void accumuateCounts(CountSumOrPercent &Sum, bool IsCS);
+
protected:
std::unique_ptr<InstrProfSymtab> Symtab;
@@ -142,6 +147,7 @@
/// Iterator over the profile data.
line_iterator Line;
bool IsIRLevelProfile = false;
+ bool HasCSIRLevelProfile = false;
Error readValueProfileData(InstrProfRecord &Record);
@@ -156,6 +162,8 @@
bool isIRLevelProfile() const override { return IsIRLevelProfile; }
+ bool hasCSIRLevelProfile() const override { return HasCSIRLevelProfile; }
+
/// Read the header.
Error readHeader() override;
@@ -212,6 +220,10 @@
return (Version & VARIANT_MASK_IR_PROF) != 0;
}
+ bool hasCSIRLevelProfile() const override {
+ return (Version & VARIANT_MASK_CSIR_PROF) != 0;
+ }
+
InstrProfSymtab &getSymtab() override {
assert(Symtab.get());
return *Symtab.get();
@@ -341,6 +353,7 @@
virtual void setValueProfDataEndianness(support::endianness Endianness) = 0;
virtual uint64_t getVersion() const = 0;
virtual bool isIRLevelProfile() const = 0;
+ virtual bool hasCSIRLevelProfile() const = 0;
virtual Error populateSymtab(InstrProfSymtab &) = 0;
};
@@ -385,6 +398,10 @@
return (FormatVersion & VARIANT_MASK_IR_PROF) != 0;
}
+ bool hasCSIRLevelProfile() const override {
+ return (FormatVersion & VARIANT_MASK_CSIR_PROF) != 0;
+ }
+
Error populateSymtab(InstrProfSymtab &Symtab) override {
return Symtab.create(HashTable->keys());
}
@@ -412,13 +429,16 @@
std::unique_ptr<InstrProfReaderRemapper> Remapper;
/// Profile summary data.
std::unique_ptr<ProfileSummary> Summary;
+ /// Context sensitive profile summary data.
+ std::unique_ptr<ProfileSummary> CS_Summary;
// Index to the current record in the record array.
unsigned RecordIndex;
// Read the profile summary. Return a pointer pointing to one byte past the
// end of the summary data if it exists or the input \c Cur.
+ // \c UseCS indicates whether to use the context-sensitive profile summary.
const unsigned char *readSummary(IndexedInstrProf::ProfVersion Version,
- const unsigned char *Cur);
+ const unsigned char *Cur, bool UseCS);
public:
IndexedInstrProfReader(
@@ -432,6 +452,9 @@
/// Return the profile version.
uint64_t getVersion() const { return Index->getVersion(); }
bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); }
+ bool hasCSIRLevelProfile() const override {
+ return Index->hasCSIRLevelProfile();
+ }
/// Return true if the given buffer is in an indexed instrprof format.
static bool hasFormat(const MemoryBuffer &DataBuffer);
@@ -450,7 +473,16 @@
std::vector<uint64_t> &Counts);
/// Return the maximum of all known function counts.
- uint64_t getMaximumFunctionCount() { return Summary->getMaxFunctionCount(); }
+ /// \c UseCS indicates whether to use the context-sensitive count.
+ uint64_t getMaximumFunctionCount(bool UseCS) {
+ if (UseCS) {
+ assert(CS_Summary && "No context sensitive profile summary");
+ return CS_Summary->getMaxFunctionCount();
+ } else {
+ assert(Summary && "No profile summary");
+ return Summary->getMaxFunctionCount();
+ }
+ }
/// Factory method to create an indexed reader.
static Expected<std::unique_ptr<IndexedInstrProfReader>>
@@ -469,7 +501,18 @@
// to be used by llvm-profdata (for dumping). Avoid using this when
// the client is the compiler.
InstrProfSymtab &getSymtab() override;
- ProfileSummary &getSummary() { return *(Summary.get()); }
+
+ /// Return the profile summary.
+ /// \c UseCS indicates whether to use the context-sensitive summary.
+ ProfileSummary &getSummary(bool UseCS) {
+ if (UseCS) {
+ assert(CS_Summary && "No context sensitive summary");
+ return *(CS_Summary.get());
+ } else {
+ assert(Summary && "No profile summary");
+ return *(Summary.get());
+ }
+ }
};
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/ProfileData/InstrProfWriter.h b/linux-x64/clang/include/llvm/ProfileData/InstrProfWriter.h
index b0ab31d..5882fa2 100644
--- a/linux-x64/clang/include/llvm/ProfileData/InstrProfWriter.h
+++ b/linux-x64/clang/include/llvm/ProfileData/InstrProfWriter.h
@@ -33,7 +33,8 @@
class InstrProfWriter {
public:
using ProfilingData = SmallDenseMap<uint64_t, InstrProfRecord>;
- enum ProfKind { PF_Unknown = 0, PF_FE, PF_IRLevel };
+ // PF_IRLevelWithCS is the profile from context sensitive IR instrumentation.
+ enum ProfKind { PF_Unknown = 0, PF_FE, PF_IRLevel, PF_IRLevelWithCS };
private:
bool Sparse;
@@ -74,20 +75,36 @@
std::unique_ptr<MemoryBuffer> writeBuffer();
/// Set the ProfileKind. Report error if mixing FE and IR level profiles.
- Error setIsIRLevelProfile(bool IsIRLevel) {
+ /// \c WithCS indicates if this is for contenxt sensitive instrumentation.
+ Error setIsIRLevelProfile(bool IsIRLevel, bool WithCS) {
if (ProfileKind == PF_Unknown) {
- ProfileKind = IsIRLevel ? PF_IRLevel: PF_FE;
+ if (IsIRLevel)
+ ProfileKind = WithCS ? PF_IRLevelWithCS : PF_IRLevel;
+ else
+ ProfileKind = PF_FE;
return Error::success();
}
- return (IsIRLevel == (ProfileKind == PF_IRLevel))
- ? Error::success()
- : make_error<InstrProfError>(
- instrprof_error::unsupported_version);
+
+ if (((ProfileKind != PF_FE) && !IsIRLevel) ||
+ ((ProfileKind == PF_FE) && IsIRLevel))
+ return make_error<InstrProfError>(instrprof_error::unsupported_version);
+
+ // When merging a context-sensitive profile (WithCS == true) with an IRLevel
+ // profile, set the kind to PF_IRLevelWithCS.
+ if (ProfileKind == PF_IRLevel && WithCS)
+ ProfileKind = PF_IRLevelWithCS;
+
+ return Error::success();
}
// Internal interface for testing purpose only.
void setValueProfDataEndianness(support::endianness Endianness);
void setOutputSparse(bool Sparse);
+ // Compute the overlap b/w this object and Other. Program level result is
+ // stored in Overlap and function level result is stored in FuncLevelOverlap.
+ void overlapRecord(NamedInstrProfRecord &&Other, OverlapStats &Overlap,
+ OverlapStats &FuncLevelOverlap,
+ const OverlapFuncFilters &FuncFilter);
private:
void addRecord(StringRef Name, uint64_t Hash, InstrProfRecord &&I,
diff --git a/linux-x64/clang/include/llvm/ProfileData/ProfileCommon.h b/linux-x64/clang/include/llvm/ProfileData/ProfileCommon.h
index b52f886..f98a343 100644
--- a/linux-x64/clang/include/llvm/ProfileData/ProfileCommon.h
+++ b/linux-x64/clang/include/llvm/ProfileData/ProfileCommon.h
@@ -83,7 +83,8 @@
SampleProfileSummaryBuilder(std::vector<uint32_t> Cutoffs)
: ProfileSummaryBuilder(std::move(Cutoffs)) {}
- void addRecord(const sampleprof::FunctionSamples &FS);
+ void addRecord(const sampleprof::FunctionSamples &FS,
+ bool isCallsiteSample = false);
std::unique_ptr<ProfileSummary> getSummary();
};
diff --git a/linux-x64/clang/include/llvm/ProfileData/SampleProf.h b/linux-x64/clang/include/llvm/ProfileData/SampleProf.h
index ca3e2de..7fbc857 100644
--- a/linux-x64/clang/include/llvm/ProfileData/SampleProf.h
+++ b/linux-x64/clang/include/llvm/ProfileData/SampleProf.h
@@ -410,6 +410,34 @@
return getNameInModule(Name, M);
}
+ /// Return the canonical name for a function, taking into account
+ /// suffix elision policy attributes.
+ static StringRef getCanonicalFnName(const Function &F) {
+ static const char *knownSuffixes[] = { ".llvm.", ".part." };
+ auto AttrName = "sample-profile-suffix-elision-policy";
+ auto Attr = F.getFnAttribute(AttrName).getValueAsString();
+ if (Attr == "" || Attr == "all") {
+ return F.getName().split('.').first;
+ } else if (Attr == "selected") {
+ StringRef Cand(F.getName());
+ for (const auto &Suf : knownSuffixes) {
+ StringRef Suffix(Suf);
+ auto It = Cand.rfind(Suffix);
+ if (It == StringRef::npos)
+ return Cand;
+ auto Dit = Cand.rfind('.');
+ if (Dit == It + Suffix.size() - 1)
+ Cand = Cand.substr(0, It);
+ }
+ return Cand;
+ } else if (Attr == "none") {
+ return F.getName();
+ } else {
+ assert(false && "internal error: unknown suffix elision policy");
+ }
+ return F.getName();
+ }
+
/// Translate \p Name into its original name in Module.
/// When the Format is not SPF_Compact_Binary, \p Name needs no translation.
/// When the Format is SPF_Compact_Binary, \p Name in current FunctionSamples
@@ -465,11 +493,9 @@
/// built in post-thin-link phase and var promotion has been done,
/// we need to add the substring of function name without the suffix
/// into the GUIDToFuncNameMap.
- auto pos = OrigName.find('.');
- if (pos != StringRef::npos) {
- StringRef NewName = OrigName.substr(0, pos);
- GUIDToFuncNameMap.insert({Function::getGUID(NewName), NewName});
- }
+ StringRef CanonName = getCanonicalFnName(F);
+ if (CanonName != OrigName)
+ GUIDToFuncNameMap.insert({Function::getGUID(CanonName), CanonName});
}
CurrentModule = &M;
}
@@ -546,10 +572,9 @@
SampleSorter(const std::map<LocationT, SampleT> &Samples) {
for (const auto &I : Samples)
V.push_back(&I);
- std::stable_sort(V.begin(), V.end(),
- [](const SamplesWithLoc *A, const SamplesWithLoc *B) {
- return A->first < B->first;
- });
+ llvm::stable_sort(V, [](const SamplesWithLoc *A, const SamplesWithLoc *B) {
+ return A->first < B->first;
+ });
}
const SamplesWithLocList &get() const { return V; }
diff --git a/linux-x64/clang/include/llvm/ProfileData/SampleProfReader.h b/linux-x64/clang/include/llvm/ProfileData/SampleProfReader.h
index 32b8f91..969cdea 100644
--- a/linux-x64/clang/include/llvm/ProfileData/SampleProfReader.h
+++ b/linux-x64/clang/include/llvm/ProfileData/SampleProfReader.h
@@ -286,10 +286,11 @@
/// Return the samples collected for function \p F.
FunctionSamples *getSamplesFor(const Function &F) {
- // The function name may have been updated by adding suffix. In sample
- // profile, the function names are all stripped, so we need to strip
- // the function name suffix before matching with profile.
- return getSamplesFor(F.getName().split('.').first);
+ // The function name may have been updated by adding suffix. Call
+ // a helper to (optionally) strip off suffixes so that we can
+ // match against the original function name in the profile.
+ StringRef CanonName = FunctionSamples::getCanonicalFnName(F);
+ return getSamplesFor(CanonName);
}
/// Return the samples collected for function \p F.