Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/llvm/llvm-project into fix/…
Browse files Browse the repository at this point in the history
…97230
  • Loading branch information
a-tarasyuk committed Jul 6, 2024
2 parents cb3c677 + d64efe4 commit 71474bc
Show file tree
Hide file tree
Showing 181 changed files with 4,481 additions and 3,064 deletions.
19 changes: 16 additions & 3 deletions bolt/include/bolt/Profile/YAMLProfileReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,29 @@ class YAMLProfileReader : public ProfileReaderBase {
bool parseFunctionProfile(BinaryFunction &Function,
const yaml::bolt::BinaryFunctionProfile &YamlBF);

/// Checks if a function profile matches a binary function.
bool profileMatches(const yaml::bolt::BinaryFunctionProfile &Profile,
const BinaryFunction &BF);

/// Infer function profile from stale data (collected on older binaries).
bool inferStaleProfile(BinaryFunction &Function,
const yaml::bolt::BinaryFunctionProfile &YamlBF);

/// Initialize maps for profile matching.
void buildNameMaps(BinaryContext &BC);

/// Matches functions using exact name.
size_t matchWithExactName();

/// Matches function using LTO comomon name.
size_t matchWithLTOCommonName();

/// Matches functions using exact hash.
size_t matchWithHash(BinaryContext &BC);

/// Matches functions with similarly named profiled functions.
size_t matchWithNameSimilarity(BinaryContext &BC);

/// Update matched YAML -> BinaryFunction pair.
void matchProfileToFunction(yaml::bolt::BinaryFunctionProfile &YamlBF,
BinaryFunction &BF) {
Expand All @@ -93,9 +109,6 @@ class YAMLProfileReader : public ProfileReaderBase {
ProfiledFunctions.emplace(&BF);
}

/// Matches functions with similarly named profiled functions.
uint64_t matchWithNameSimilarity(BinaryContext &BC);

/// Check if the profile uses an event with a given \p Name.
bool usesEvent(StringRef Name) const;
};
Expand Down
3 changes: 3 additions & 0 deletions bolt/lib/Profile/BoltAddressTranslation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ void BoltAddressTranslation::write(const BinaryContext &BC, raw_ostream &OS) {
LLVM_DEBUG(dbgs() << " Cold part\n");
for (const FunctionFragment &FF :
Function.getLayout().getSplitFragments()) {
// Skip empty fragments to avoid adding zero-address entries to maps.
if (FF.empty())
continue;
ColdPartSource.emplace(FF.getAddress(), Function.getOutputAddress());
Map.clear();
for (const BinaryBasicBlock *const BB : FF)
Expand Down
183 changes: 97 additions & 86 deletions bolt/lib/Profile/YAMLProfileReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,13 @@ Error YAMLProfileReader::preprocessProfile(BinaryContext &BC) {
return Error::success();
}

bool YAMLProfileReader::profileMatches(
const yaml::bolt::BinaryFunctionProfile &Profile, const BinaryFunction &BF) {
if (opts::IgnoreHash)
return Profile.NumBasicBlocks == BF.size();
return Profile.Hash == static_cast<uint64_t>(BF.getHash());
}

bool YAMLProfileReader::mayHaveProfileData(const BinaryFunction &BF) {
if (opts::MatchProfileWithFunctionHash)
return true;
Expand All @@ -358,8 +365,92 @@ bool YAMLProfileReader::mayHaveProfileData(const BinaryFunction &BF) {
return false;
}

uint64_t YAMLProfileReader::matchWithNameSimilarity(BinaryContext &BC) {
uint64_t MatchedWithNameSimilarity = 0;
size_t YAMLProfileReader::matchWithExactName() {
size_t MatchedWithExactName = 0;
// This first pass assigns profiles that match 100% by name and by hash.
for (auto [YamlBF, BF] : llvm::zip_equal(YamlBP.Functions, ProfileBFs)) {
if (!BF)
continue;
BinaryFunction &Function = *BF;
// Clear function call count that may have been set while pre-processing
// the profile.
Function.setExecutionCount(BinaryFunction::COUNT_NO_PROFILE);

if (profileMatches(YamlBF, Function)) {
matchProfileToFunction(YamlBF, Function);
++MatchedWithExactName;
}
}
return MatchedWithExactName;
}

size_t YAMLProfileReader::matchWithHash(BinaryContext &BC) {
// Iterates through profiled functions to match the first binary function with
// the same exact hash. Serves to match identical, renamed functions.
// Collisions are possible where multiple functions share the same exact hash.
size_t MatchedWithHash = 0;
if (opts::MatchProfileWithFunctionHash) {
DenseMap<size_t, BinaryFunction *> StrictHashToBF;
StrictHashToBF.reserve(BC.getBinaryFunctions().size());

for (auto &[_, BF] : BC.getBinaryFunctions())
StrictHashToBF[BF.getHash()] = &BF;

for (yaml::bolt::BinaryFunctionProfile &YamlBF : YamlBP.Functions) {
if (YamlBF.Used)
continue;
auto It = StrictHashToBF.find(YamlBF.Hash);
if (It != StrictHashToBF.end() && !ProfiledFunctions.count(It->second)) {
BinaryFunction *BF = It->second;
matchProfileToFunction(YamlBF, *BF);
++MatchedWithHash;
}
}
}
return MatchedWithHash;
}

size_t YAMLProfileReader::matchWithLTOCommonName() {
// This second pass allows name ambiguity for LTO private functions.
size_t MatchedWithLTOCommonName = 0;
for (const auto &[CommonName, LTOProfiles] : LTOCommonNameMap) {
if (!LTOCommonNameFunctionMap.contains(CommonName))
continue;
std::unordered_set<BinaryFunction *> &Functions =
LTOCommonNameFunctionMap[CommonName];
// Return true if a given profile is matched to one of BinaryFunctions with
// matching LTO common name.
auto matchProfile = [&](yaml::bolt::BinaryFunctionProfile *YamlBF) {
if (YamlBF->Used)
return false;
for (BinaryFunction *BF : Functions) {
if (!ProfiledFunctions.count(BF) && profileMatches(*YamlBF, *BF)) {
matchProfileToFunction(*YamlBF, *BF);
++MatchedWithLTOCommonName;
return true;
}
}
return false;
};
bool ProfileMatched = llvm::any_of(LTOProfiles, matchProfile);

// If there's only one function with a given name, try to match it
// partially.
if (!ProfileMatched && LTOProfiles.size() == 1 && Functions.size() == 1 &&
!LTOProfiles.front()->Used &&
!ProfiledFunctions.count(*Functions.begin())) {
matchProfileToFunction(*LTOProfiles.front(), **Functions.begin());
++MatchedWithLTOCommonName;
}
}
return MatchedWithLTOCommonName;
}

size_t YAMLProfileReader::matchWithNameSimilarity(BinaryContext &BC) {
if (opts::NameSimilarityFunctionMatchingThreshold == 0)
return 0;

size_t MatchedWithNameSimilarity = 0;
ItaniumPartialDemangler Demangler;

// Demangle and derive namespace from function name.
Expand Down Expand Up @@ -477,17 +568,6 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
}
YamlProfileToFunction.resize(YamlBP.Functions.size() + 1);

auto profileMatches = [](const yaml::bolt::BinaryFunctionProfile &Profile,
BinaryFunction &BF) {
if (opts::IgnoreHash)
return Profile.NumBasicBlocks == BF.size();
return Profile.Hash == static_cast<uint64_t>(BF.getHash());
};

uint64_t MatchedWithExactName = 0;
uint64_t MatchedWithHash = 0;
uint64_t MatchedWithLTOCommonName = 0;

// Computes hash for binary functions.
if (opts::MatchProfileWithFunctionHash) {
for (auto &[_, BF] : BC.getBinaryFunctions()) {
Expand All @@ -501,84 +581,15 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
}
}

// This first pass assigns profiles that match 100% by name and by hash.
for (auto [YamlBF, BF] : llvm::zip_equal(YamlBP.Functions, ProfileBFs)) {
if (!BF)
continue;
BinaryFunction &Function = *BF;
// Clear function call count that may have been set while pre-processing
// the profile.
Function.setExecutionCount(BinaryFunction::COUNT_NO_PROFILE);

if (profileMatches(YamlBF, Function)) {
matchProfileToFunction(YamlBF, Function);
++MatchedWithExactName;
}
}

// Iterates through profiled functions to match the first binary function with
// the same exact hash. Serves to match identical, renamed functions.
// Collisions are possible where multiple functions share the same exact hash.
if (opts::MatchProfileWithFunctionHash) {
DenseMap<size_t, BinaryFunction *> StrictHashToBF;
StrictHashToBF.reserve(BC.getBinaryFunctions().size());

for (auto &[_, BF] : BC.getBinaryFunctions())
StrictHashToBF[BF.getHash()] = &BF;

for (yaml::bolt::BinaryFunctionProfile &YamlBF : YamlBP.Functions) {
if (YamlBF.Used)
continue;
auto It = StrictHashToBF.find(YamlBF.Hash);
if (It != StrictHashToBF.end() && !ProfiledFunctions.count(It->second)) {
BinaryFunction *BF = It->second;
matchProfileToFunction(YamlBF, *BF);
++MatchedWithHash;
}
}
}

// This second pass allows name ambiguity for LTO private functions.
for (const auto &[CommonName, LTOProfiles] : LTOCommonNameMap) {
if (!LTOCommonNameFunctionMap.contains(CommonName))
continue;
std::unordered_set<BinaryFunction *> &Functions =
LTOCommonNameFunctionMap[CommonName];
// Return true if a given profile is matched to one of BinaryFunctions with
// matching LTO common name.
auto matchProfile = [&](yaml::bolt::BinaryFunctionProfile *YamlBF) {
if (YamlBF->Used)
return false;
for (BinaryFunction *BF : Functions) {
if (!ProfiledFunctions.count(BF) && profileMatches(*YamlBF, *BF)) {
matchProfileToFunction(*YamlBF, *BF);
++MatchedWithLTOCommonName;
return true;
}
}
return false;
};
bool ProfileMatched = llvm::any_of(LTOProfiles, matchProfile);

// If there's only one function with a given name, try to match it
// partially.
if (!ProfileMatched && LTOProfiles.size() == 1 && Functions.size() == 1 &&
!LTOProfiles.front()->Used &&
!ProfiledFunctions.count(*Functions.begin())) {
matchProfileToFunction(*LTOProfiles.front(), **Functions.begin());
++MatchedWithLTOCommonName;
}
}
const size_t MatchedWithExactName = matchWithExactName();
const size_t MatchedWithHash = matchWithHash(BC);
const size_t MatchedWithLTOCommonName = matchWithLTOCommonName();
const size_t MatchedWithNameSimilarity = matchWithNameSimilarity(BC);

for (auto [YamlBF, BF] : llvm::zip_equal(YamlBP.Functions, ProfileBFs))
if (!YamlBF.Used && BF && !ProfiledFunctions.count(BF))
matchProfileToFunction(YamlBF, *BF);

// Uses name similarity to match functions that were not matched by name.
uint64_t MatchedWithNameSimilarity =
opts::NameSimilarityFunctionMatchingThreshold > 0
? matchWithNameSimilarity(BC)
: 0;

for (yaml::bolt::BinaryFunctionProfile &YamlBF : YamlBP.Functions)
if (!YamlBF.Used && opts::Verbosity >= 1)
Expand Down
4 changes: 4 additions & 0 deletions bolt/test/X86/register-fragments-bolt-symbols.s
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@
# PREAGGWARM: B X:0 #chain.warm# 1 0
# RUN: perf2bolt %t.warm.bolt -p %t.preagg.warm --pa -o %t.warm.fdata -w %t.warm.yaml \
# RUN: -v=1 | FileCheck %s --check-prefix=CHECK-BOLT-WARM
# RUN: FileCheck %s --input-file %t.warm.fdata --check-prefix=CHECK-FDATA-WARM
# RUN: FileCheck %s --input-file %t.warm.yaml --check-prefix=CHECK-YAML-WARM

# CHECK-BOLT-WARM: marking chain.warm/1(*2) as a fragment of chain
# CHECK-FDATA-WARM: chain
# CHECK-YAML-WARM: chain

# RUN: sed -i 's|chain|chain/2|g' %t.fdata
# RUN: llvm-objcopy --localize-symbol=chain %t.main.o
Expand Down
2 changes: 1 addition & 1 deletion clang/cmake/caches/Fuchsia-stage2.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ if(WIN32 OR LLVM_WINSYSROOT)
set(RUNTIMES_${target}_CMAKE_MODULE_LINKER_FLAGS ${WINDOWS_LINK_FLAGS} CACHE STRING "")
endif()

foreach(target aarch64-unknown-linux-gnu;armv7-unknown-linux-gnueabihf;i386-unknown-linux-gnu;riscv64-unknown-linux-gnu;x86_64-unknown-linux-gnu)
foreach(target aarch64-linux-gnu;armv7-linux-gnueabihf;i386-linux-gnu;riscv64-linux-gnu;x86_64-linux-gnu)
if(LINUX_${target}_SYSROOT)
# Set the per-target builtins options.
list(APPEND BUILTIN_TARGETS "${target}")
Expand Down
16 changes: 13 additions & 3 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -236,9 +236,6 @@ C++20 Feature Support
``<expected>`` from libstdc++ to work correctly with Clang.

- User defined constructors are allowed for copy-list-initialization with CTAD.
The example code for deduction guides for std::map in
(`cppreference <https://en.cppreference.com/w/cpp/container/map/deduction_guides>`_)
will now work.
(#GH62925).

C++23 Feature Support
Expand Down Expand Up @@ -272,6 +269,7 @@ C++2c Feature Support

- Implemented `P2809R3: Trivial infinite loops are not Undefined Behavior <https://wg21.link/P2809R3>`_.

- Implemented `P3144R2 Deleting a Pointer to an Incomplete Type Should be Ill-formed <https://wg21.link/P3144R2>`_.

Resolutions to C++ Defect Reports
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -438,6 +436,12 @@ New Compiler Flags
Matches MSVC behaviour by defining ``__STDC__`` to ``1`` when
MSVC compatibility mode is used. It has no effect for C++ code.

- ``-Wc++23-compat`` group was added to help migrating existing codebases
to C++23.

- ``-Wc++2c-compat`` group was added to help migrating existing codebases
to upcoming C++26.

Deprecated Compiler Flags
-------------------------

Expand Down Expand Up @@ -476,6 +480,10 @@ Modified Compiler Flags
evaluating to ``true`` and an empty body such as ``while(1);``)
are considered infinite, even when the ``-ffinite-loop`` flag is set.

- Diagnostics groups about compatibility with a particular C++ Standard version
now include dianostics about C++26 features that are not present in older
versions.

Removed Compiler Flags
-------------------------

Expand Down Expand Up @@ -963,6 +971,8 @@ Bug Fixes to C++ Support
- Fixed an assertion failure about invalid conversion when calling lambda. (#GH96205).
- Fixed a bug where the first operand of binary ``operator&`` would be transformed as if it was the operand
of the address of operator. (#GH97483).
- Fixed an assertion failure about a constant expression which is a known integer but is not
evaluated to an integer. (#GH96670).
- Fix a crash when checking destructor reference with an invalid initializer. (#GH97230).

Bug Fixes to AST Handling
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/AST/ASTConsumer.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ namespace clang {
class ASTDeserializationListener; // layering violation because void* is ugly
class SemaConsumer; // layering violation required for safe SemaConsumer
class TagDecl;
class DeclaratorDecl;
class VarDecl;
class FunctionDecl;
class ImportDecl;
Expand Down Expand Up @@ -105,7 +106,7 @@ class ASTConsumer {
/// CompleteExternalDeclaration - Callback invoked at the end of a translation
/// unit to notify the consumer that the given external declaration should be
/// completed.
virtual void CompleteExternalDeclaration(VarDecl *D) {}
virtual void CompleteExternalDeclaration(DeclaratorDecl *D) {}

/// Callback invoked when an MSInheritanceAttr has been attached to a
/// CXXRecordDecl.
Expand Down
Loading

0 comments on commit 71474bc

Please sign in to comment.