Skip to content

Commit 9b02a91

Browse files
committed
Merge branch 'main' of https://github.com/llvm/llvm-project into main-merge-fake16
2 parents d80b7b0 + f4be681 commit 9b02a91

File tree

933 files changed

+32033
-13000
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

933 files changed

+32033
-13000
lines changed

bolt/CMakeLists.txt

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
1+
cmake_minimum_required(VERSION 3.20.0)
2+
13
set(LLVM_SUBPROJECT_TITLE "BOLT")
24

3-
include(ExternalProject)
5+
if(NOT DEFINED LLVM_COMMON_CMAKE_UTILS)
6+
set(LLVM_COMMON_CMAKE_UTILS ${CMAKE_CURRENT_SOURCE_DIR}/../cmake)
7+
endif()
8+
include(${LLVM_COMMON_CMAKE_UTILS}/Modules/CMakePolicy.cmake
9+
NO_POLICY_SCOPE)
10+
11+
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
12+
project(bolt)
13+
set(BOLT_BUILT_STANDALONE TRUE)
14+
endif()
415

516
set(BOLT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
617
set(BOLT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
@@ -9,6 +20,42 @@ set(CMAKE_CXX_STANDARD 17)
920
# Add path for custom modules.
1021
list(INSERT CMAKE_MODULE_PATH 0 "${BOLT_SOURCE_DIR}/cmake/modules")
1122

23+
include(GNUInstallDirs)
24+
25+
# standalone build, copied from clang
26+
if(BOLT_BUILT_STANDALONE)
27+
set(CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard to conform to")
28+
set(CMAKE_CXX_STANDARD_REQUIRED YES)
29+
set(CMAKE_CXX_EXTENSIONS NO)
30+
31+
if(NOT MSVC_IDE)
32+
set(LLVM_ENABLE_ASSERTIONS ${ENABLE_ASSERTIONS}
33+
CACHE BOOL "Enable assertions")
34+
# Assertions should follow llvm-config's.
35+
mark_as_advanced(LLVM_ENABLE_ASSERTIONS)
36+
endif()
37+
38+
find_package(LLVM REQUIRED HINTS "${LLVM_CMAKE_DIR}")
39+
list(APPEND CMAKE_MODULE_PATH "${LLVM_DIR}")
40+
41+
set(LLVM_MAIN_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../llvm" CACHE PATH "Path to LLVM source tree")
42+
find_program(LLVM_TABLEGEN_EXE "llvm-tblgen" ${LLVM_TOOLS_BINARY_DIR}
43+
NO_DEFAULT_PATH)
44+
45+
# They are used as destination of target generators.
46+
set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin)
47+
set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX})
48+
49+
include(AddLLVM)
50+
include(TableGen)
51+
include_directories(${LLVM_INCLUDE_DIRS})
52+
link_directories("${LLVM_LIBRARY_DIR}")
53+
54+
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_INSTALL_BINDIR}" )
55+
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_INSTALL_LIBDIR}/${LLVM_LIBDIR_SUFFIX}" )
56+
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_INSTALL_LIBDIR}/${LLVM_LIBDIR_SUFFIX}")
57+
endif() # standalone
58+
1259
# Determine default set of targets to build -- the intersection of
1360
# those BOLT supports and those LLVM is targeting.
1461
set(BOLT_TARGETS_TO_BUILD_all "AArch64;X86;RISCV")
@@ -94,6 +141,8 @@ if (BOLT_ENABLE_RUNTIME)
94141
if(CMAKE_SYSROOT)
95142
list(APPEND extra_args -DCMAKE_SYSROOT=${CMAKE_SYSROOT})
96143
endif()
144+
145+
include(ExternalProject)
97146
ExternalProject_Add(bolt_rt
98147
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/runtime"
99148
STAMP_DIR ${CMAKE_CURRENT_BINARY_DIR}/bolt_rt-stamps
@@ -104,6 +153,7 @@ if (BOLT_ENABLE_RUNTIME)
104153
-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}
105154
-DLLVM_LIBDIR_SUFFIX=${LLVM_LIBDIR_SUFFIX}
106155
-DLLVM_LIBRARY_DIR=${LLVM_LIBRARY_DIR}
156+
-DBOLT_BUILT_STANDALONE=${BOLT_BUILT_STANDALONE}
107157
${extra_args}
108158
INSTALL_COMMAND ""
109159
BUILD_ALWAYS True
@@ -113,6 +163,8 @@ if (BOLT_ENABLE_RUNTIME)
113163
add_llvm_install_targets(install-bolt_rt
114164
DEPENDS bolt_rt bolt
115165
COMPONENT bolt)
166+
set(LIBBOLT_RT_INSTR "${CMAKE_CURRENT_BINARY_DIR}/bolt_rt-bins/lib/libbolt_rt_instr.a")
167+
set(LIBBOLT_RT_HUGIFY "${CMAKE_CURRENT_BINARY_DIR}/bolt_rt-bins/lib/libbolt_rt_hugify.a")
116168
endif()
117169

118170
find_program(GNU_LD_EXECUTABLE NAMES ${LLVM_DEFAULT_TARGET_TRIPLE}-ld.bfd ld.bfd DOC "GNU ld")

bolt/include/bolt/Core/BinaryContext.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "bolt/RuntimeLibs/RuntimeLibrary.h"
2424
#include "llvm/ADT/AddressRanges.h"
2525
#include "llvm/ADT/ArrayRef.h"
26+
#include "llvm/ADT/EquivalenceClasses.h"
2627
#include "llvm/ADT/StringMap.h"
2728
#include "llvm/ADT/iterator.h"
2829
#include "llvm/BinaryFormat/Dwarf.h"
@@ -241,6 +242,10 @@ class BinaryContext {
241242
/// Function fragments to skip.
242243
std::unordered_set<BinaryFunction *> FragmentsToSkip;
243244

245+
/// Fragment equivalence classes to query belonging to the same "family" in
246+
/// presence of multiple fragments/multiple parents.
247+
EquivalenceClasses<const BinaryFunction *> FragmentClasses;
248+
244249
/// The runtime library.
245250
std::unique_ptr<RuntimeLibrary> RtLibrary;
246251

@@ -1032,7 +1037,15 @@ class BinaryContext {
10321037
/// fragment_name == parent_name.cold(.\d+)?
10331038
/// True if the Function is registered, false if the check failed.
10341039
bool registerFragment(BinaryFunction &TargetFunction,
1035-
BinaryFunction &Function) const;
1040+
BinaryFunction &Function);
1041+
1042+
/// Return true if two functions belong to the same "family": are fragments
1043+
/// of one another, or fragments of the same parent, or transitively fragment-
1044+
/// related.
1045+
bool areRelatedFragments(const BinaryFunction *LHS,
1046+
const BinaryFunction *RHS) const {
1047+
return FragmentClasses.isEquivalent(LHS, RHS);
1048+
}
10361049

10371050
/// Add interprocedural reference for \p Function to \p Address
10381051
void addInterproceduralReference(BinaryFunction *Function, uint64_t Address) {

bolt/include/bolt/Core/BinaryFunction.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1793,11 +1793,6 @@ class BinaryFunction {
17931793
return ParentFragments.contains(&Other);
17941794
}
17951795

1796-
/// Returns if this function is a parent of \p Other function.
1797-
bool isParentOf(const BinaryFunction &Other) const {
1798-
return Fragments.contains(&Other);
1799-
}
1800-
18011796
/// Return the child fragment form parent function
18021797
iterator_range<FragmentsSetTy::const_iterator> getFragments() const {
18031798
return iterator_range<FragmentsSetTy::const_iterator>(Fragments.begin(),
@@ -1807,11 +1802,6 @@ class BinaryFunction {
18071802
/// Return the parent function for split function fragments.
18081803
FragmentsSetTy *getParentFragments() { return &ParentFragments; }
18091804

1810-
/// Returns if this function is a parent or child of \p Other function.
1811-
bool isParentOrChildOf(const BinaryFunction &Other) const {
1812-
return isChildOf(Other) || isParentOf(Other);
1813-
}
1814-
18151805
/// Set the profile data for the number of times the function was called.
18161806
BinaryFunction &setExecutionCount(uint64_t Count) {
18171807
ExecutionCount = Count;

bolt/include/bolt/RuntimeLibs/RuntimeLibrary.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,16 @@ class RuntimeLibrary {
5858
uint64_t RuntimeFiniAddress{0};
5959
uint64_t RuntimeStartAddress{0};
6060

61-
/// Get the full path to a runtime library specified by \p LibFileName.
61+
/// Get the full path to a runtime library specified by \p LibFileName and \p
62+
/// ToolPath.
63+
static std::string getLibPathByToolPath(StringRef ToolPath,
64+
StringRef LibFileName);
65+
66+
/// Get the full path to a runtime library by the install directory.
67+
static std::string getLibPathByInstalled(StringRef LibFileName);
68+
69+
/// Gets the full path to a runtime library based on whether it exists
70+
/// in the install libdir or runtime libdir.
6271
static std::string getLibPath(StringRef ToolPath, StringRef LibFileName);
6372

6473
/// Load a static runtime library specified by \p LibPath.

bolt/lib/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
add_compile_definitions(CMAKE_INSTALL_FULL_LIBDIR="${CMAKE_INSTALL_FULL_LIBDIR}")
2+
13
add_subdirectory(Core)
24
add_subdirectory(Passes)
35
add_subdirectory(Profile)

bolt/lib/Core/BinaryContext.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ bool BinaryContext::analyzeJumpTable(const uint64_t Address,
646646
const BinaryFunction *TargetBF = getBinaryFunctionContainingAddress(Value);
647647
const bool DoesBelongToFunction =
648648
BF.containsAddress(Value) ||
649-
(TargetBF && TargetBF->isParentOrChildOf(BF));
649+
(TargetBF && areRelatedFragments(TargetBF, &BF));
650650
if (!DoesBelongToFunction) {
651651
LLVM_DEBUG({
652652
if (!BF.containsAddress(Value)) {
@@ -839,9 +839,11 @@ BinaryContext::getOrCreateJumpTable(BinaryFunction &Function, uint64_t Address,
839839
assert(Address == JT->getAddress() && "unexpected non-empty jump table");
840840

841841
// Prevent associating a jump table to a specific fragment twice.
842-
// This simple check arises from the assumption: no more than 2 fragments.
843-
if (JT->Parents.size() == 1 && JT->Parents[0] != &Function) {
844-
assert(JT->Parents[0]->isParentOrChildOf(Function) &&
842+
if (!llvm::is_contained(JT->Parents, &Function)) {
843+
assert(llvm::all_of(JT->Parents,
844+
[&](const BinaryFunction *BF) {
845+
return areRelatedFragments(&Function, BF);
846+
}) &&
845847
"cannot re-use jump table of a different function");
846848
// Duplicate the entry for the parent function for easy access
847849
JT->Parents.push_back(&Function);
@@ -852,8 +854,8 @@ BinaryContext::getOrCreateJumpTable(BinaryFunction &Function, uint64_t Address,
852854
JT->print(this->outs());
853855
}
854856
Function.JumpTables.emplace(Address, JT);
855-
JT->Parents[0]->setHasIndirectTargetToSplitFragment(true);
856-
JT->Parents[1]->setHasIndirectTargetToSplitFragment(true);
857+
for (BinaryFunction *Parent : JT->Parents)
858+
Parent->setHasIndirectTargetToSplitFragment(true);
857859
}
858860

859861
bool IsJumpTableParent = false;
@@ -1209,12 +1211,13 @@ void BinaryContext::generateSymbolHashes() {
12091211
}
12101212

12111213
bool BinaryContext::registerFragment(BinaryFunction &TargetFunction,
1212-
BinaryFunction &Function) const {
1214+
BinaryFunction &Function) {
12131215
assert(TargetFunction.isFragment() && "TargetFunction must be a fragment");
12141216
if (TargetFunction.isChildOf(Function))
12151217
return true;
12161218
TargetFunction.addParentFragment(Function);
12171219
Function.addFragment(TargetFunction);
1220+
FragmentClasses.unionSets(&TargetFunction, &Function);
12181221
if (!HasRelocations) {
12191222
TargetFunction.setSimple(false);
12201223
Function.setSimple(false);
@@ -1336,7 +1339,7 @@ void BinaryContext::processInterproceduralReferences() {
13361339

13371340
if (TargetFunction) {
13381341
if (TargetFunction->isFragment() &&
1339-
!TargetFunction->isChildOf(Function)) {
1342+
!areRelatedFragments(TargetFunction, &Function)) {
13401343
this->errs()
13411344
<< "BOLT-WARNING: interprocedural reference between unrelated "
13421345
"fragments: "

bolt/lib/Core/Exceptions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ Error BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
207207
"BOLT-ERROR: cannot find landing pad fragment");
208208
BC.addInterproceduralReference(this, Fragment->getAddress());
209209
BC.processInterproceduralReferences();
210-
assert(isParentOrChildOf(*Fragment) &&
210+
assert(BC.areRelatedFragments(this, Fragment) &&
211211
"BOLT-ERROR: cannot have landing pads in different functions");
212212
setHasIndirectTargetToSplitFragment(true);
213213
BC.addFragmentsToSkip(this);

bolt/lib/Profile/DataAggregator.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ MaxSamples("max-samples",
8888
cl::cat(AggregatorCategory));
8989

9090
extern cl::opt<opts::ProfileFormatKind> ProfileFormat;
91+
extern cl::opt<bool> ProfileUsePseudoProbes;
9192
extern cl::opt<std::string> SaveProfile;
9293

9394
cl::opt<bool> ReadPreAggregated(
@@ -2298,7 +2299,8 @@ std::error_code DataAggregator::writeBATYAML(BinaryContext &BC,
22982299

22992300
yaml::bolt::BinaryProfile BP;
23002301

2301-
const MCPseudoProbeDecoder *PseudoProbeDecoder = BC.getPseudoProbeDecoder();
2302+
const MCPseudoProbeDecoder *PseudoProbeDecoder =
2303+
opts::ProfileUsePseudoProbes ? BC.getPseudoProbeDecoder() : nullptr;
23022304

23032305
// Fill out the header info.
23042306
BP.Header.Version = 1;

bolt/lib/Profile/YAMLProfileReader.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ llvm::cl::opt<bool>
4949
llvm::cl::opt<bool> ProfileUseDFS("profile-use-dfs",
5050
cl::desc("use DFS order for YAML profile"),
5151
cl::Hidden, cl::cat(BoltOptCategory));
52+
53+
llvm::cl::opt<bool> ProfileUsePseudoProbes(
54+
"profile-use-pseudo-probes",
55+
cl::desc("Use pseudo probes for profile generation and matching"),
56+
cl::Hidden, cl::cat(BoltOptCategory));
5257
} // namespace opts
5358

5459
namespace llvm {

bolt/lib/Profile/YAMLProfileWriter.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
namespace opts {
2424
extern llvm::cl::opt<bool> ProfileUseDFS;
25+
extern llvm::cl::opt<bool> ProfileUsePseudoProbes;
2526
} // namespace opts
2627

2728
namespace llvm {
@@ -57,7 +58,8 @@ YAMLProfileWriter::convert(const BinaryFunction &BF, bool UseDFS,
5758
const BoltAddressTranslation *BAT) {
5859
yaml::bolt::BinaryFunctionProfile YamlBF;
5960
const BinaryContext &BC = BF.getBinaryContext();
60-
const MCPseudoProbeDecoder *PseudoProbeDecoder = BC.getPseudoProbeDecoder();
61+
const MCPseudoProbeDecoder *PseudoProbeDecoder =
62+
opts::ProfileUsePseudoProbes ? BC.getPseudoProbeDecoder() : nullptr;
6163

6264
const uint16_t LBRProfile = BF.getProfileFlags() & BinaryFunction::PF_LBR;
6365

bolt/lib/Rewrite/PseudoProbeRewriter.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ static cl::opt<PrintPseudoProbesOptions> PrintPseudoProbes(
4949
clEnumValN(PPP_All, "all", "enable all debugging printout")),
5050
cl::Hidden, cl::cat(BoltCategory));
5151

52+
extern cl::opt<bool> ProfileUsePseudoProbes;
5253
} // namespace opts
5354

5455
namespace {
@@ -89,12 +90,15 @@ class PseudoProbeRewriter final : public MetadataRewriter {
8990
};
9091

9192
Error PseudoProbeRewriter::preCFGInitializer() {
92-
parsePseudoProbe();
93+
if (opts::ProfileUsePseudoProbes)
94+
parsePseudoProbe();
9395

9496
return Error::success();
9597
}
9698

9799
Error PseudoProbeRewriter::postEmitFinalizer() {
100+
if (!opts::ProfileUsePseudoProbes)
101+
parsePseudoProbe();
98102
updatePseudoProbes();
99103

100104
return Error::success();

bolt/lib/RuntimeLibs/HugifyRuntimeLibrary.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ cl::opt<bool>
3232
"(which is what --hot-text relies on)."),
3333
cl::cat(BoltOptCategory));
3434

35-
static cl::opt<std::string> RuntimeHugifyLib(
36-
"runtime-hugify-lib",
37-
cl::desc("specify file name of the runtime hugify library"),
38-
cl::init("libbolt_rt_hugify.a"), cl::cat(BoltOptCategory));
35+
static cl::opt<std::string>
36+
RuntimeHugifyLib("runtime-hugify-lib",
37+
cl::desc("specify path of the runtime hugify library"),
38+
cl::init("libbolt_rt_hugify.a"), cl::cat(BoltOptCategory));
3939

4040
} // namespace opts
4141

bolt/lib/RuntimeLibs/InstrumentationRuntimeLibrary.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ namespace opts {
2626

2727
cl::opt<std::string> RuntimeInstrumentationLib(
2828
"runtime-instrumentation-lib",
29-
cl::desc("specify file name of the runtime instrumentation library"),
29+
cl::desc("specify path of the runtime instrumentation library"),
3030
cl::init("libbolt_rt_instr.a"), cl::cat(BoltOptCategory));
3131

3232
extern cl::opt<bool> InstrumentationFileAppendPID;

bolt/lib/RuntimeLibs/RuntimeLibrary.cpp

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ using namespace bolt;
2626

2727
void RuntimeLibrary::anchor() {}
2828

29-
std::string RuntimeLibrary::getLibPath(StringRef ToolPath,
30-
StringRef LibFileName) {
29+
std::string RuntimeLibrary::getLibPathByToolPath(StringRef ToolPath,
30+
StringRef LibFileName) {
3131
StringRef Dir = llvm::sys::path::parent_path(ToolPath);
3232
SmallString<128> LibPath = llvm::sys::path::parent_path(Dir);
3333
llvm::sys::path::append(LibPath, "lib" LLVM_LIBDIR_SUFFIX);
@@ -38,13 +38,36 @@ std::string RuntimeLibrary::getLibPath(StringRef ToolPath,
3838
llvm::sys::path::append(LibPath, "lib" LLVM_LIBDIR_SUFFIX);
3939
}
4040
llvm::sys::path::append(LibPath, LibFileName);
41-
if (!llvm::sys::fs::exists(LibPath)) {
42-
errs() << "BOLT-ERROR: library not found: " << LibPath << "\n";
43-
exit(1);
44-
}
4541
return std::string(LibPath);
4642
}
4743

44+
std::string RuntimeLibrary::getLibPathByInstalled(StringRef LibFileName) {
45+
SmallString<128> LibPath(CMAKE_INSTALL_FULL_LIBDIR);
46+
llvm::sys::path::append(LibPath, LibFileName);
47+
return std::string(LibPath);
48+
}
49+
50+
std::string RuntimeLibrary::getLibPath(StringRef ToolPath,
51+
StringRef LibFileName) {
52+
if (llvm::sys::fs::exists(LibFileName)) {
53+
return std::string(LibFileName);
54+
}
55+
56+
std::string ByTool = getLibPathByToolPath(ToolPath, LibFileName);
57+
if (llvm::sys::fs::exists(ByTool)) {
58+
return ByTool;
59+
}
60+
61+
std::string ByInstalled = getLibPathByInstalled(LibFileName);
62+
if (llvm::sys::fs::exists(ByInstalled)) {
63+
return ByInstalled;
64+
}
65+
66+
errs() << "BOLT-ERROR: library not found: " << ByTool << ", " << ByInstalled
67+
<< ", or " << LibFileName << "\n";
68+
exit(1);
69+
}
70+
4871
void RuntimeLibrary::loadLibrary(StringRef LibPath, BOLTLinker &Linker,
4972
BOLTLinker::SectionsMapper MapSections) {
5073
ErrorOr<std::unique_ptr<MemoryBuffer>> MaybeBuf =

0 commit comments

Comments
 (0)