Skip to content

Commit f0cc969

Browse files
committed
Adding Matching and Inference Functionality to Propeller
1 parent e04f4df commit f0cc969

23 files changed

+668
-35
lines changed

clang/include/clang/Basic/CodeGenOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,9 @@ class CodeGenOptions : public CodeGenOptionsBase {
288288
/// Name of the profile file to use with -fprofile-sample-use.
289289
std::string SampleProfileFile;
290290

291+
/// Name of the profile file to use with -fpropeller-profile-use.
292+
std::string PropellerProfileFile;
293+
291294
/// Name of the profile file to use as output for with -fmemory-profile.
292295
std::string MemoryProfileOutput;
293296

clang/include/clang/Driver/Options.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1672,6 +1672,11 @@ def fprofile_sample_accurate : Flag<["-"], "fprofile-sample-accurate">,
16721672
as cold. Otherwise, treat callsites without profile samples as if
16731673
we have no profile}]>,
16741674
MarshallingInfoFlag<CodeGenOpts<"ProfileSampleAccurate">>;
1675+
def fpropeller_profile_use_EQ : Joined<["-"], "fpropeller-profile-use=">,
1676+
Group<f_Group>, Visibility<[ClangOption, CC1Option, CLOption]>,
1677+
MetaVarName<"<pathname>">,
1678+
HelpText<"Use propeller profile for profile-guided optimization">,
1679+
MarshallingInfoString<CodeGenOpts<"PropellerProfileFile">>;
16751680
def fsample_profile_use_profi : Flag<["-"], "fsample-profile-use-profi">,
16761681
Visibility<[ClangOption, CC1Option]>,
16771682
Group<f_Group>,

clang/lib/CodeGen/BackendUtil.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -835,7 +835,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
835835
if (CodeGenOpts.hasProfileIRInstr())
836836
// -fprofile-generate.
837837
PGOOpt = PGOOptions(getProfileGenName(CodeGenOpts), "", "",
838-
CodeGenOpts.MemoryProfileUsePath, nullptr,
838+
CodeGenOpts.MemoryProfileUsePath,
839+
CodeGenOpts.PropellerProfileFile, nullptr,
839840
PGOOptions::IRInstr, PGOOptions::NoCSAction,
840841
ClPGOColdFuncAttr, CodeGenOpts.DebugInfoForProfiling,
841842
/*PseudoProbeForProfiling=*/false,
@@ -846,30 +847,41 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
846847
: PGOOptions::NoCSAction;
847848
PGOOpt = PGOOptions(CodeGenOpts.ProfileInstrumentUsePath, "",
848849
CodeGenOpts.ProfileRemappingFile,
849-
CodeGenOpts.MemoryProfileUsePath, VFS,
850+
CodeGenOpts.MemoryProfileUsePath,
851+
CodeGenOpts.PropellerProfileFile, VFS,
850852
PGOOptions::IRUse, CSAction, ClPGOColdFuncAttr,
851853
CodeGenOpts.DebugInfoForProfiling);
852854
} else if (!CodeGenOpts.SampleProfileFile.empty())
853855
// -fprofile-sample-use
854856
PGOOpt = PGOOptions(
855857
CodeGenOpts.SampleProfileFile, "", CodeGenOpts.ProfileRemappingFile,
856-
CodeGenOpts.MemoryProfileUsePath, VFS, PGOOptions::SampleUse,
858+
CodeGenOpts.MemoryProfileUsePath,
859+
CodeGenOpts.PropellerProfileFile, VFS, PGOOptions::SampleUse,
857860
PGOOptions::NoCSAction, ClPGOColdFuncAttr,
858861
CodeGenOpts.DebugInfoForProfiling, CodeGenOpts.PseudoProbeForProfiling);
859862
else if (!CodeGenOpts.MemoryProfileUsePath.empty())
860863
// -fmemory-profile-use (without any of the above options)
861-
PGOOpt = PGOOptions("", "", "", CodeGenOpts.MemoryProfileUsePath, VFS,
864+
PGOOpt = PGOOptions("", "", "", CodeGenOpts.MemoryProfileUsePath,
865+
CodeGenOpts.PropellerProfileFile, VFS,
862866
PGOOptions::NoAction, PGOOptions::NoCSAction,
863867
ClPGOColdFuncAttr, CodeGenOpts.DebugInfoForProfiling);
868+
else if (!CodeGenOpts.PropellerProfileFile.empty())
869+
// -fpropeller-profile-use (without any of the above options)
870+
PGOOpt = PGOOptions("", "", "", "",
871+
CodeGenOpts.PropellerProfileFile, VFS,
872+
PGOOptions::NoAction, PGOOptions::NoCSAction,
873+
ClPGOColdFuncAttr, CodeGenOpts.DebugInfoForProfiling);
864874
else if (CodeGenOpts.PseudoProbeForProfiling)
865875
// -fpseudo-probe-for-profiling
866876
PGOOpt =
867-
PGOOptions("", "", "", /*MemoryProfile=*/"", nullptr,
877+
PGOOptions("", "", "", /*MemoryProfile=*/"",
878+
/*PropellerProfileFile=*/"", nullptr,
868879
PGOOptions::NoAction, PGOOptions::NoCSAction,
869880
ClPGOColdFuncAttr, CodeGenOpts.DebugInfoForProfiling, true);
870881
else if (CodeGenOpts.DebugInfoForProfiling)
871882
// -fdebug-info-for-profiling
872-
PGOOpt = PGOOptions("", "", "", /*MemoryProfile=*/"", nullptr,
883+
PGOOpt = PGOOptions("", "", "", /*MemoryProfile=*/"",
884+
/*PropellerProfileFile=*/"", nullptr,
873885
PGOOptions::NoAction, PGOOptions::NoCSAction,
874886
ClPGOColdFuncAttr, true);
875887

@@ -887,7 +899,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
887899
PGOOpt->CSAction = PGOOptions::CSIRInstr;
888900
} else
889901
PGOOpt = PGOOptions("", getProfileGenName(CodeGenOpts), "",
890-
/*MemoryProfile=*/"", nullptr, PGOOptions::NoAction,
902+
/*MemoryProfile=*/"", /*PropellerProfileFile=*/"",
903+
nullptr, PGOOptions::NoAction,
891904
PGOOptions::CSIRInstr, ClPGOColdFuncAttr,
892905
CodeGenOpts.DebugInfoForProfiling);
893906
}
@@ -1320,6 +1333,7 @@ runThinLTOBackend(CompilerInstance &CI, ModuleSummaryIndex *CombinedIndex,
13201333
Conf.OptLevel = CGOpts.OptimizationLevel;
13211334
initTargetOptions(CI, Diags, Conf.Options);
13221335
Conf.SampleProfile = std::move(SampleProfile);
1336+
Conf.PropellerProfile = CGOpts.PropellerProfileFile;
13231337
Conf.PTO.LoopUnrolling = CGOpts.UnrollLoops;
13241338
Conf.PTO.LoopInterchange = CGOpts.InterchangeLoops;
13251339
// For historical reasons, loop interleaving is set to mirror setting for loop

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6416,6 +6416,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
64166416
CmdArgs.push_back("-sample-profile-use-profi");
64176417
}
64186418

6419+
if (auto *PropellerUseArg =
6420+
Args.getLastArg(options::OPT_fpropeller_profile_use_EQ)) {
6421+
if (Arg *A = Args.getLastArg(options::OPT_fbasic_block_sections_EQ)) {
6422+
StringRef Val = A->getValue();
6423+
if (Val.starts_with("list="))
6424+
D.Diag(diag::err_drv_argument_not_allowed_with)
6425+
<< PropellerUseArg->getAsString(Args)
6426+
<< "-fbasic-block-sections=list";
6427+
}
6428+
PropellerUseArg->render(Args, CmdArgs);
6429+
}
6430+
64196431
// Add runtime flag for PS4/PS5 when PGO, coverage, or sanitizers are enabled.
64206432
if (RawTriple.isPS() &&
64216433
!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {

lld/ELF/Config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ struct Config {
211211
llvm::StringRef ltoNewPmPasses;
212212
llvm::StringRef ltoObjPath;
213213
llvm::StringRef ltoSampleProfile;
214+
llvm::StringRef ltoPropellerProfile;
214215
llvm::StringRef mapFile;
215216
llvm::StringRef outputFile;
216217
llvm::StringRef optRemarksFilename;

lld/ELF/Driver.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,6 +1245,73 @@ static SmallVector<StringRef, 0> getSymbolOrderingFile(Ctx &ctx,
12451245
return names.takeVector();
12461246
}
12471247

1248+
struct HotBBInfo{
1249+
uint32_t TotalBBSize = 0;
1250+
uint32_t HotBBSize = 0;
1251+
};
1252+
static SmallVector<StringRef, 0> generateSymbolOrderingFromPropellerProfile(MemoryBufferRef mb) {
1253+
SmallVector<std::pair<StringRef, HotBBInfo>> names;
1254+
SmallVector<HotBBInfo *> hotBBInfos;
1255+
uint32_t line = 0;
1256+
for (StringRef s : args::getLines(mb)) {
1257+
line++;
1258+
if (!s.consume_front("!") || s.empty()) {
1259+
error("invalid propeller profile at line: " + Twine(line));
1260+
}
1261+
if (s.consume_front("!")) {
1262+
SmallVector<StringRef, 3> HotBB;
1263+
s.split(HotBB, ' ');
1264+
if (HotBB.size() != 3)
1265+
error("invalid propeller profile at line: " + Twine(line));
1266+
HotBB[0].consume_front("0x");
1267+
unsigned long long Hash, Freq, BBID;
1268+
if (getAsUnsignedInteger(HotBB[0], 16, Hash))
1269+
error("invalid propeller profile at line: " + Twine(line));
1270+
if (getAsUnsignedInteger(HotBB[1], 10, Freq))
1271+
error("invalid propeller profile at line: " + Twine(line));
1272+
if (getAsUnsignedInteger(HotBB[2], 10, BBID))
1273+
error("invalid propeller profile at line: " + Twine(line));
1274+
if (Freq > 0 || BBID == 0) {
1275+
for (auto hotBBInfo : hotBBInfos) {
1276+
hotBBInfo->HotBBSize++;
1277+
}
1278+
}
1279+
}
1280+
else {
1281+
hotBBInfos.clear();
1282+
SmallVector<StringRef, 2> NamesWithTotalBBSize;
1283+
s.split(NamesWithTotalBBSize, ' ');
1284+
if (NamesWithTotalBBSize.size() != 2)
1285+
error("invalid propeller profile at line: " + Twine(line));
1286+
unsigned long long TotalBBSize;
1287+
if (getAsUnsignedInteger(NamesWithTotalBBSize[1], 10, TotalBBSize))
1288+
error("invalid propeller profile at line: " + Twine(line));
1289+
SmallVector<StringRef> funcNames;
1290+
NamesWithTotalBBSize[0].split(funcNames, '/');
1291+
for (auto funcName : funcNames) {
1292+
names.push_back({funcName, {static_cast<uint32_t>(TotalBBSize), 0}});
1293+
hotBBInfos.push_back(&names.back().second);
1294+
}
1295+
}
1296+
}
1297+
SmallVector<StringRef, 0> symorders;
1298+
static std::vector<std::string> storedStrings;
1299+
for (auto item : names) {
1300+
if (item.second.HotBBSize > 0) {
1301+
symorders.push_back(item.first);
1302+
}
1303+
}
1304+
for (auto item : names) {
1305+
if (item.second.HotBBSize != item.second.TotalBBSize) {
1306+
std::string str(item.first.str());
1307+
str.append(".cold");
1308+
storedStrings.push_back(str);
1309+
symorders.emplace_back(storedStrings.back());
1310+
}
1311+
}
1312+
return symorders;
1313+
}
1314+
12481315
static bool getIsRela(Ctx &ctx, opt::InputArgList &args) {
12491316
// The psABI specifies the default relocation entry format.
12501317
bool rela = is_contained({EM_AARCH64, EM_AMDGPU, EM_HEXAGON, EM_LOONGARCH,
@@ -1848,6 +1915,16 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
18481915
ctx.arg.symbolOrderingFile = getSymbolOrderingFile(ctx, *buffer);
18491916
}
18501917

1918+
if (auto *arg = args.getLastArg(OPT_propeller_profile_use)){
1919+
if (args.hasArg(OPT_call_graph_ordering_file) || args.hasArg(OPT_symbol_ordering_file))
1920+
error("--propeller-profile-use and --symbol-ordering-file and --call-graph-order-file "
1921+
"may not be used together");
1922+
if (auto buffer = readFile(ctx, arg->getValue())) {
1923+
ctx.arg.ltoPropellerProfile = arg->getValue();
1924+
ctx.arg.symbolOrderingFile = generateSymbolOrderingFromPropellerProfile(*buffer);
1925+
}
1926+
}
1927+
18511928
assert(ctx.arg.versionDefinitions.empty());
18521929
ctx.arg.versionDefinitions.push_back(
18531930
{"local", (uint16_t)VER_NDX_LOCAL, {}, {}});

lld/ELF/LTO.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ static lto::Config createConfig(Ctx &ctx) {
128128
c.StatsFile = std::string(ctx.arg.optStatsFilename);
129129

130130
c.SampleProfile = std::string(ctx.arg.ltoSampleProfile);
131+
c.PropellerProfile = std::string(ctx.arg.ltoPropellerProfile);
131132
for (StringRef pluginFn : ctx.arg.passPlugins)
132133
c.PassPlugins.push_back(std::string(pluginFn));
133134
c.DebugPassManager = ctx.arg.ltoDebugPassManager;

lld/ELF/Options.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,9 @@ def print_map: F<"print-map">,
408408
def print_memory_usage: F<"print-memory-usage">,
409409
HelpText<"Report target memory usage">;
410410

411+
defm propeller_profile_use:
412+
EEq<"propeller-profile-use", "Propeller profile file used to reorder symorder">;
413+
411414
defm relax: BB<"relax",
412415
"Enable target-specific relaxations if supported (default)",
413416
"Disable target-specific relaxations">;
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#ifndef LLVM_CODEGEN_FuncHotBBHashesProfileReader_H
2+
#define LLVM_CODEGEN_FuncHotBBHashesProfileReader_H
3+
4+
#include "llvm/ADT/SmallString.h"
5+
#include "llvm/IR/Module.h"
6+
#include "llvm/InitializePasses.h"
7+
#include "llvm/Pass.h"
8+
#include "llvm/Support/MemoryBuffer.h"
9+
10+
namespace llvm {
11+
12+
struct HotBBInfo {
13+
uint64_t BBHash;
14+
uint64_t Freq;
15+
};
16+
17+
class FuncHotBBHashesProfileReader : public ImmutablePass {
18+
public:
19+
static char ID;
20+
21+
FuncHotBBHashesProfileReader(const std::string PropellerProfile);
22+
23+
FuncHotBBHashesProfileReader();
24+
25+
StringRef getPassName() const override {
26+
return "Basic Block Frequency with Hash Profile Reader";
27+
}
28+
29+
// return a vector of hit BB hashes for a function.
30+
std::pair<bool, SmallVector<HotBBInfo, 4>>
31+
getHotBBInfosForFunction(StringRef FuncName) const;
32+
33+
// Reads the profile for matching functions.
34+
bool doInitialization(Module &M) override;
35+
36+
private:
37+
std::unique_ptr<MemoryBuffer> MBuf;
38+
39+
StringRef getAliasName(StringRef FuncName) const {
40+
auto R = FuncAliasMap.find(FuncName);
41+
return R == FuncAliasMap.end() ? FuncName : R->second;
42+
}
43+
44+
// Reads the basic block frequency with hash profile for functions in this module.
45+
Error ReadProfile();
46+
47+
// Profile file path.
48+
std::string PropellerFilePath;
49+
50+
// Some functions have alias names. We use this map to find the main alias
51+
// name for which we have mapping in ProgramBBClusterInfo.
52+
StringMap<StringRef> FuncAliasMap;
53+
54+
// record the frequency of basic block,
55+
// the basic block is represented by its hash.
56+
StringMap<SmallVector<HotBBInfo, 4>> FuncToHotBBHashes;
57+
};
58+
59+
ImmutablePass *
60+
createFuncHotBBHashesProfileReaderPass(const std::string PropellerProfile);
61+
62+
} // namespace llvm
63+
64+
#endif // LLVM_CODEGEN_FuncHotBBHashesProfileReader_H
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#ifndef LLVM_CODEGEN_HotMachineBasicBlockInfoGenerator_H
2+
#define LLVM_CODEGEN_HotMachineBasicBlockInfoGenerator_H
3+
4+
#include "llvm/CodeGen/MachineFunctionPass.h"
5+
#include "llvm/Transforms/Utils/SampleProfileInference.h"
6+
#include "llvm/CodeGen/FuncHotBBHashesProfileReader.h"
7+
8+
namespace llvm {
9+
10+
class HotMachineBasicBlockInfoGenerator : public MachineFunctionPass {
11+
public:
12+
static char ID;
13+
HotMachineBasicBlockInfoGenerator();
14+
15+
StringRef getPassName() const override {
16+
return "Basic Block Matching and Inference";
17+
}
18+
19+
void getAnalysisUsage(AnalysisUsage &AU) const override;
20+
21+
bool runOnMachineFunction(MachineFunction &F) override;
22+
23+
std::optional<SmallVector<MachineBasicBlock *, 4>> getHotMBBs(StringRef FuncName) const;
24+
25+
private:
26+
using Edge = std::pair<const MachineBasicBlock *, const MachineBasicBlock *>;
27+
using BlockWeightMap = DenseMap<const MachineBasicBlock *, uint64_t>;
28+
using EdgeWeightMap = DenseMap<Edge, uint64_t>;
29+
using BlockEdgeMap =
30+
DenseMap<const MachineBasicBlock *, SmallVector<const MachineBasicBlock *, 8>>;
31+
32+
DenseMap<StringRef, SmallVector<MachineBasicBlock *, 4>> FuncToHotMBBs;
33+
34+
void matchHotBBsByHashes(
35+
MachineFunction &MF,
36+
SmallVector<HotBBInfo, 4> &HotMBBInfos,
37+
BlockWeightMap &MBBToFreq,
38+
BlockEdgeMap &Successors,
39+
SmallVector<MachineBasicBlock *, 4> &HotBBs);
40+
41+
void generateHotBBsforFunction(
42+
MachineFunction &MF,
43+
BlockWeightMap &OriBlockWeights,
44+
BlockWeightMap &BlockWeights,
45+
EdgeWeightMap &EdgeWeights,
46+
SmallVector<MachineBasicBlock *, 4> &HotBBs);
47+
};
48+
49+
} // end namespace llvm
50+
51+
#endif // LLVM_CODEGEN_HotMachineBasicBlockInfoGenerator_H

0 commit comments

Comments
 (0)