Skip to content

Commit d38f3d8

Browse files
committed
Add clang frontend flags for MIP
Add clang frontend flags for machine profiles. * `-fmachine-profile-generate` * Produce an instrumented binary * `-fmachine-profile-function-coverage` * Only profile function coverage * `-fmachine-profile-block-coverage` * Profile basic block coverage * `-fmachine-profile-link-unit-name=` * Specify a name to identify the current link unit * `-fno-machine-profile-runtime` * Do not link the MIP runtime * `-fno-machine-profile-dump` * Do not dump the raw profile data when the program exits * `-fmachine-profile-selected-function-group=`, `-fmachine-profile-function-group-count=` * Only instrument group `i` of `N` total groups of functions * `-fmachine-profile-use=` * Use the provided profile for optimization
1 parent e4717a3 commit d38f3d8

File tree

19 files changed

+264
-1
lines changed

19 files changed

+264
-1
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,6 +1187,43 @@ defm coverage_mapping : BoolFOption<"coverage-mapping",
11871187
CodeGenOpts<"CoverageMapping">, DefaultFalse,
11881188
PosFlag<SetTrue, [CC1Option], "Generate coverage mapping to enable code coverage analysis">,
11891189
NegFlag<SetFalse, [], "Disable code coverage analysis">, BothFlags<[CoreOption]>>;
1190+
1191+
def fmachine_profile_generate : Flag<["-"], "fmachine-profile-generate">, Group<f_Group>, Flags<[CC1Option]>,
1192+
HelpText<"Generate MIP instrumented code.">;
1193+
def fno_machine_profile_generate : Flag<["-"], "fno-machine-profile-generate">, Group<f_Group>, Flags<[CC1Option]>,
1194+
HelpText<"Disable MIP instrumented code.">;
1195+
def fmachine_profile_function_coverage : Flag<["-"], "fmachine-profile-function-coverage">, Group<f_Group>,
1196+
Flags<[CC1Option]>, HelpText<"Enable MIP machine function coverage instrumentation.">;
1197+
def fno_machine_profile_function_coverage : Flag<["-"], "fno-machine-profile-function-coverage">, Group<f_Group>,
1198+
Flags<[CC1Option]>, HelpText<"Disable MIP machine function coverage instrumentation.">;
1199+
def fmachine_profile_block_coverage : Flag<["-"], "fmachine-profile-block-coverage">, Group<f_Group>,
1200+
Flags<[CC1Option]>, HelpText<"Enable MIP machine basic block coverage instrumentation.">;
1201+
def fno_machine_profile_block_coverage : Flag<["-"], "fno-machine-profile-block-coverage">, Group<f_Group>,
1202+
Flags<[CC1Option]>, HelpText<"Disable MIP machine basic block coverage instrumentation.">;
1203+
def fmachine_profile_call_graph : Flag<["-"], "fmachine-profile-call-graph">, Group<f_Group>, Flags<[CC1Option]>,
1204+
HelpText<"Enable full MIP instrumentation. Cannot be used with -fmachine-profile-function-coverage.">;
1205+
def fno_machine_profile_call_graph : Flag<["-"], "fno-machine-profile-call-graph">, Group<f_Group>, Flags<[CC1Option]>,
1206+
HelpText<"Disable full MIP instrumentation.">;
1207+
def fmachine_profile_runtime_buffer_EQ : Joined<["-"], "fmachine-profile-runtime-buffer=">, Group<f_Group>,
1208+
Flags<[CC1Option]>, MetaVarName<"<RuntimeBufferSize>">,
1209+
HelpText<"Allocate a buffer of <RuntimeBufferSize> bytes to hold machine function call samples.">;
1210+
def fmachine_profile_link_unit_name_EQ : Joined<["-"], "fmachine-profile-link-unit-name=">,
1211+
Group<f_Group>, Flags<[CC1Option]>, MetaVarName<"<LinkUnitName>">,
1212+
HelpText<"Use <LinkUnitName> to identify this link unit.">;
1213+
def fno_machine_profile_runtime : Flag<["-"], "fno-machine-profile-runtime">, Group<f_Group>, Flags<[CC1Option]>,
1214+
HelpText<"Do not link the machine profile runtime.">;
1215+
def fno_machine_profile_dump : Flag<["-"], "fno-machine-profile-dump">, Group<f_Group>, Flags<[CC1Option]>,
1216+
HelpText<"Do not dump a raw machine profile when the program exits.">;
1217+
def fmachine_profile_function_group_count_EQ : Joined<["-"], "fmachine-profile-function-group-count=">, Group<f_Group>,
1218+
Flags<[CC1Option]>, MetaVarName<"<N>">,
1219+
HelpText<"Partition the machine functions into <N> groups and instrument the group specified by -fmachine-profile-selected-function-group.">;
1220+
def fmachine_profile_selected_function_group_EQ : Joined<["-"], "fmachine-profile-selected-function-group=">,
1221+
Group<f_Group>, Flags<[CC1Option]>, MetaVarName<"<i>">,
1222+
HelpText<"Instrument only group <i>. Must be in the range [0, -fmachine-profile-function-group-count).">;
1223+
def fmachine_profile_use_EQ : Joined<["-"], "fmachine-profile-use=">,
1224+
Group<f_Group>, Flags<[CC1Option]>, MetaVarName<"<pathnames>">,
1225+
HelpText<"Use MIP profile data from <pathnames> for profile-guided optimization, where <pathnames> is a comma separated ordered list of .mip profiles.">;
1226+
11901227
def fprofile_generate : Flag<["-"], "fprofile-generate">,
11911228
Group<f_Group>, Flags<[CoreOption]>,
11921229
HelpText<"Generate instrumented code to collect execution counts into default.profraw (overridden by LLVM_PROFILE_FILE env var)">;

clang/include/clang/Driver/ToolChain.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,9 @@ class ToolChain {
457457
/// needsProfileRT - returns true if instrumentation profile is on.
458458
static bool needsProfileRT(const llvm::opt::ArgList &Args);
459459

460+
/// Returns true if machine profile instrumentation is on.
461+
static bool needsMachineProfileRT(const llvm::opt::ArgList &Args);
462+
460463
/// Returns true if gcov instrumentation (-fprofile-arcs or --coverage) is on.
461464
static bool needsGCovInstrumentation(const llvm::opt::ArgList &Args);
462465

@@ -660,6 +663,11 @@ class ToolChain {
660663
virtual void addProfileRTLibs(const llvm::opt::ArgList &Args,
661664
llvm::opt::ArgStringList &CmdArgs) const;
662665

666+
/// addMachineProfileRTLibs - When -fmachine-profile-generate is specified,
667+
/// try to pass a suitable profile runtime library to the linker.
668+
virtual void addMachineProfileRTLibs(const llvm::opt::ArgList &Args,
669+
llvm::opt::ArgStringList &CmdArgs) const;
670+
663671
/// Add arguments to use system-specific CUDA includes.
664672
virtual void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
665673
llvm::opt::ArgStringList &CC1Args) const;

clang/lib/Driver/ToolChain.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,12 @@ bool ToolChain::needsProfileRT(const ArgList &Args) {
517517
Args.hasArg(options::OPT_forder_file_instrumentation);
518518
}
519519

520+
bool ToolChain::needsMachineProfileRT(const ArgList &Args) {
521+
return Args.hasFlag(options::OPT_fmachine_profile_generate,
522+
options::OPT_fno_machine_profile_generate, false) &&
523+
!Args.hasArg(options::OPT_fno_machine_profile_runtime);
524+
}
525+
520526
bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) {
521527
return Args.hasArg(options::OPT_coverage) ||
522528
Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
@@ -749,6 +755,14 @@ void ToolChain::addProfileRTLibs(const llvm::opt::ArgList &Args,
749755
CmdArgs.push_back(getCompilerRTArgString(Args, "profile"));
750756
}
751757

758+
void ToolChain::addMachineProfileRTLibs(
759+
const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const {
760+
if (!needsMachineProfileRT(Args))
761+
return;
762+
763+
CmdArgs.push_back(getCompilerRTArgString(Args, "mip"));
764+
}
765+
752766
ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType(
753767
const ArgList &Args) const {
754768
if (runtimeLibType)

clang/lib/Driver/ToolChains/AIX.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
155155
if (getToolChain().ShouldLinkCXXStdlib(Args))
156156
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
157157

158+
ToolChain.addMachineProfileRTLibs(Args, CmdArgs);
159+
158160
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
159161
AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
160162

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,6 +967,97 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C,
967967
}
968968
}
969969

970+
static void addMachineProfileFlags(const Driver &D, const ArgList &Args,
971+
ArgStringList &CmdArgs) {
972+
// FIXME: Machine profile generation flags need to be added to linker args
973+
// when LTO is on.
974+
if (!D.isUsingLTO()) {
975+
bool HasMIPFlags = false;
976+
if (Args.hasFlag(options::OPT_fmachine_profile_generate,
977+
options::OPT_fno_machine_profile_generate, false)) {
978+
CmdArgs.push_back("-mllvm");
979+
CmdArgs.push_back("-enable-machine-instrumentation");
980+
// TODO: Add a tool to run `llvm-objcopy` and `llvm-mipdata` to fully
981+
// extract and create an empty .mip file after the link step.
982+
HasMIPFlags = true;
983+
}
984+
985+
if (Arg *A = Args.getLastArg(options::OPT_fmachine_profile_use_EQ)) {
986+
StringRef value = A->getValue();
987+
CmdArgs.push_back("-mllvm");
988+
CmdArgs.push_back(Args.MakeArgString("-machine-profile-use=" + value));
989+
HasMIPFlags = true;
990+
}
991+
992+
if (!HasMIPFlags)
993+
return;
994+
995+
std::string LinkUnitName;
996+
if (const Arg *A =
997+
Args.getLastArg(options::OPT_fmachine_profile_link_unit_name_EQ)) {
998+
LinkUnitName = A->getValue();
999+
} else if (const Arg *A = Args.getLastArg(options::OPT_o)) {
1000+
LinkUnitName = A->getValue();
1001+
} else {
1002+
LinkUnitName = D.getDefaultImageName();
1003+
}
1004+
CmdArgs.push_back("-mllvm");
1005+
CmdArgs.push_back(Args.MakeArgString("-link-unit-name=" + LinkUnitName));
1006+
1007+
if (Args.hasFlag(options::OPT_fmachine_profile_function_coverage,
1008+
options::OPT_fno_machine_profile_function_coverage,
1009+
false)) {
1010+
CmdArgs.push_back("-mllvm");
1011+
CmdArgs.push_back("-enable-machine-function-coverage");
1012+
} else if (Args.hasFlag(options::OPT_fmachine_profile_call_graph,
1013+
options::OPT_fno_machine_profile_call_graph,
1014+
true)) {
1015+
CmdArgs.push_back("-mllvm");
1016+
CmdArgs.push_back("-enable-machine-call-graph");
1017+
}
1018+
1019+
if (Args.hasFlag(options::OPT_fmachine_profile_block_coverage,
1020+
options::OPT_fno_machine_profile_block_coverage, false)) {
1021+
CmdArgs.push_back("-mllvm");
1022+
CmdArgs.push_back("-enable-machine-block-coverage");
1023+
}
1024+
1025+
if (const Arg *A =
1026+
Args.getLastArg(options::OPT_fmachine_profile_runtime_buffer_EQ)) {
1027+
StringRef S = A->getValue();
1028+
unsigned RuntimeBufferSize;
1029+
if (S.getAsInteger(0, RuntimeBufferSize))
1030+
D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
1031+
CmdArgs.push_back("-mllvm");
1032+
CmdArgs.push_back(Args.MakeArgString("-machine-profile-runtime-buffer=" +
1033+
Twine(RuntimeBufferSize)));
1034+
}
1035+
1036+
unsigned GroupCount = 1;
1037+
if (const Arg *A = Args.getLastArg(
1038+
options::OPT_fmachine_profile_function_group_count_EQ)) {
1039+
StringRef S = A->getValue();
1040+
if (S.getAsInteger(0, GroupCount) || GroupCount < 1)
1041+
D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
1042+
// TODO: Add these args in the linker if we are using LTO.
1043+
CmdArgs.push_back("-mllvm");
1044+
CmdArgs.push_back(Args.MakeArgString(
1045+
"-machine-profile-function-group-count=" + Twine(GroupCount)));
1046+
}
1047+
1048+
if (const Arg *A = Args.getLastArg(
1049+
options::OPT_fmachine_profile_selected_function_group_EQ)) {
1050+
unsigned SelectedGroup;
1051+
StringRef S = A->getValue();
1052+
if (S.getAsInteger(0, SelectedGroup) || SelectedGroup >= GroupCount)
1053+
D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
1054+
CmdArgs.push_back("-mllvm");
1055+
CmdArgs.push_back(Args.MakeArgString(
1056+
"-machine-profile-selected-function-group=" + Twine(SelectedGroup)));
1057+
}
1058+
}
1059+
}
1060+
9701061
/// Check whether the given input tree contains any compilation actions.
9711062
static bool ContainsCompileAction(const Action *A) {
9721063
if (isa<CompileJobAction>(A) || isa<BackendJobAction>(A))
@@ -5304,6 +5395,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
53045395
if (!Triple.isNVPTX() && !Triple.isAMDGCN())
53055396
addPGOAndCoverageFlags(TC, C, D, Output, Args, CmdArgs);
53065397

5398+
addMachineProfileFlags(D, Args, CmdArgs);
5399+
53075400
Args.AddLastArg(CmdArgs, options::OPT_fclang_abi_compat_EQ);
53085401

53095402
// Add runtime flag for PS4 when PGO, coverage, or sanitizers are enabled.

clang/lib/Driver/ToolChains/Darwin.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "clang/Driver/Options.h"
2020
#include "clang/Driver/SanitizerArgs.h"
2121
#include "llvm/ADT/StringSwitch.h"
22+
#include "llvm/MIP/MIP.h"
2223
#include "llvm/Option/ArgList.h"
2324
#include "llvm/ProfileData/InstrProf.h"
2425
#include "llvm/Support/Path.h"
@@ -657,6 +658,7 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
657658
CmdArgs.push_back("-allow_stack_execute");
658659

659660
getMachOToolChain().addProfileRTLibs(Args, CmdArgs);
661+
getMachOToolChain().addMachineProfileRTLibs(Args, CmdArgs);
660662

661663
StringRef Parallelism = getLTOParallelism(Args, getToolChain().getDriver());
662664
if (!Parallelism.empty()) {
@@ -1259,6 +1261,18 @@ void Darwin::addProfileRTLibs(const ArgList &Args,
12591261
}
12601262
}
12611263

1264+
void Darwin::addMachineProfileRTLibs(const ArgList &Args,
1265+
ArgStringList &CmdArgs) const {
1266+
if (!needsMachineProfileRT(Args))
1267+
return;
1268+
1269+
AddLinkRuntimeLib(Args, CmdArgs, "mip",
1270+
RuntimeLinkOptions(RLO_AlwaysLink | RLO_FirstLink));
1271+
1272+
if (hasExportSymbolDirective(Args))
1273+
addExportedSymbol(CmdArgs, MIP_RUNTIME_SYMBOL_NAME);
1274+
}
1275+
12621276
void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args,
12631277
ArgStringList &CmdArgs,
12641278
StringRef Sanitizer,

clang/lib/Driver/ToolChains/Darwin.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,14 @@ class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain {
202202
// There aren't any profiling libs for embedded targets currently.
203203
}
204204

205+
/// Add any profiling runtime libraries that are needed. This is essentially a
206+
/// MachO specific version of addMachineProfileRT in Tools.cpp.
207+
void
208+
addMachineProfileRTLibs(const llvm::opt::ArgList &Args,
209+
llvm::opt::ArgStringList &CmdArgs) const override {
210+
// There aren't any profiling libs for embedded targets currently.
211+
}
212+
205213
/// }
206214
/// @name ToolChain Implementation
207215
/// {
@@ -329,6 +337,10 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public MachO {
329337
void addProfileRTLibs(const llvm::opt::ArgList &Args,
330338
llvm::opt::ArgStringList &CmdArgs) const override;
331339

340+
void
341+
addMachineProfileRTLibs(const llvm::opt::ArgList &Args,
342+
llvm::opt::ArgStringList &CmdArgs) const override;
343+
332344
protected:
333345
/// }
334346
/// @name Darwin specific Toolchain functions

clang/lib/Driver/ToolChains/DragonFly.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
169169
}
170170

171171
getToolChain().addProfileRTLibs(Args, CmdArgs);
172+
getToolChain().addMachineProfileRTLibs(Args, CmdArgs);
172173

173174
const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
174175
C.addCommand(std::make_unique<Command>(JA, *this,

clang/lib/Driver/ToolChains/FreeBSD.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
365365
}
366366

367367
ToolChain.addProfileRTLibs(Args, CmdArgs);
368+
ToolChain.addMachineProfileRTLibs(Args, CmdArgs);
368369

369370
const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
370371
C.addCommand(std::make_unique<Command>(JA, *this,

clang/lib/Driver/ToolChains/Fuchsia.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "clang/Driver/DriverDiagnostic.h"
1515
#include "clang/Driver/Options.h"
1616
#include "clang/Driver/SanitizerArgs.h"
17+
#include "llvm/MIP/MIP.h"
1718
#include "llvm/Option/ArgList.h"
1819
#include "llvm/ProfileData/InstrProf.h"
1920
#include "llvm/Support/FileSystem.h"
@@ -128,6 +129,7 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
128129
bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
129130
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
130131
ToolChain.addProfileRTLibs(Args, CmdArgs);
132+
ToolChain.addMachineProfileRTLibs(Args, CmdArgs);
131133

132134
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
133135
if (Args.hasArg(options::OPT_static))
@@ -447,3 +449,14 @@ void Fuchsia::addProfileRTLibs(const llvm::opt::ArgList &Args,
447449
Twine("-u", llvm::getInstrProfRuntimeHookVarName())));
448450
ToolChain::addProfileRTLibs(Args, CmdArgs);
449451
}
452+
453+
void Fuchsia::addMachineProfileRTLibs(const llvm::opt::ArgList &Args,
454+
llvm::opt::ArgStringList &CmdArgs) const {
455+
// Add linker option -u__llvm_mip_runtime to cause runtime
456+
// initialization module to be linked in.
457+
if (needsMachineProfileRT(Args) &&
458+
!Args.hasArg(options::OPT_fno_machine_profile_dump)) {
459+
CmdArgs.push_back(Args.MakeArgString("-u" MIP_RUNTIME_SYMBOL_NAME));
460+
}
461+
ToolChain::addProfileRTLibs(Args, CmdArgs);
462+
}

0 commit comments

Comments
 (0)