Skip to content

Commit

Permalink
add: get function score to find hot functions refine the dumped csv f…
Browse files Browse the repository at this point in the history
…ormat

Summary: minor modification of the bolt stoke pass

(cherry picked from FBD5471011)
  • Loading branch information
yzhao30 authored and maksfb committed Jul 13, 2017
1 parent 6d84571 commit 70bad8d
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 53 deletions.
88 changes: 41 additions & 47 deletions bolt/Passes/StokeInfo.cpp
@@ -1,42 +1,37 @@
#include "StokeInfo.h"
#include "llvm/Support/Options.h"

#undef DEBUG_TYPE
#define DEBUG_TYPE "stoke"

using namespace llvm;
using namespace bolt;

namespace opts {

cl::OptionCategory StokeOptCategory("STOKE generic options");
cl::OptionCategory StokeOptCategory("STOKE pass options");

static cl::opt<std::string>
StokeOutputDataFilename("stoke-data",
cl::desc("<info data for stoke>"),
StokeOutputDataFilename("stoke-out",
cl::desc("output data for stoke's use"),
cl::Optional,
cl::cat(StokeOptCategory));
}

namespace llvm {
namespace bolt {

void dumpRegNameFromBitVec(const BitVector &RegV, const BinaryContext &BC) {
dbgs() << "\t ";
int RegIdx = RegV.find_first();
while (RegIdx != -1) {
dbgs() << RegIdx << ":" << BC.MRI->getName(RegIdx) << " ";
RegIdx = RegV.find_next(RegIdx);
}
dbgs() << "\n";
}

void getRegNameFromBitVec(const BitVector &RegV, std::set<std::string> &NameVec,
const BinaryContext &BC) {
void getRegNameFromBitVec(const BinaryContext &BC, const BitVector &RegV,
std::set<std::string> *NameVec = nullptr) {
int RegIdx = RegV.find_first();
while (RegIdx != -1) {
dbgs() << RegIdx << BC.MRI->getName(RegIdx) << "<>";
NameVec.insert(std::string(BC.MRI->getName(RegIdx)));
DEBUG(dbgs() << BC.MRI->getName(RegIdx) << " ");
if (NameVec) {
NameVec->insert(std::string(BC.MRI->getName(RegIdx)));
}
RegIdx = RegV.find_next(RegIdx);
}
dbgs() << "\n";
DEBUG(dbgs() << "\n");
}

void StokeInfo::checkInstr(const BinaryContext &BC, const BinaryFunction &BF,
Expand All @@ -54,13 +49,9 @@ void StokeInfo::checkInstr(const BinaryContext &BC, const BinaryFunction &BF,
}
// skip function with exception handling yet
if (BC.MIA->isEHLabel(It) || BC.MIA->isInvoke(It) || BC.MIA->hasEHInfo(It)) {
outs() << "\t exception\n";
FuncInfo.Omitted = true;
return;
}
if (BC.MIA->hasRIPOperand(It)) {
outs() << "\t rip operand\n";
}
// check if this function contains call instruction
if (BC.MIA->isCall(It)) {
FuncInfo.HasCall = true;
Expand All @@ -69,19 +60,21 @@ void StokeInfo::checkInstr(const BinaryContext &BC, const BinaryFunction &BF,
if (TargetSymbol == nullptr) {
FuncInfo.Omitted = true;
return;
} else {
outs() << "\t calling " << TargetSymbol->getName() << "\n";
}
}
// check if this function modify stack or heap
// TODO: more accurate analysis
auto IsPush = BC.MIA->isPush(It);
auto IsRipAddr = BC.MIA->hasRIPOperand(It);
if (IsPush) {
FuncInfo.StackOut = true;
}
if (BC.MIA->isStore(It) && !IsPush && !BC.MIA->hasRIPOperand(It)) {
if (BC.MIA->isStore(It) && !IsPush && !IsRipAddr) {
FuncInfo.HeapOut = true;
}
if (IsRipAddr) {
FuncInfo.HasRipAddr = true;
}

} // end of for (auto &It : ...)
} // end of for (auto *BB : ...)
Expand All @@ -102,41 +95,42 @@ bool StokeInfo::analyze(const BinaryContext &BC, BinaryFunction &BF,
FuncInfo.Offset = BF.getFileOffset();
FuncInfo.Size = BF.getMaxSize();
FuncInfo.NumInstrs = BF.getNumNonPseudos();
FuncInfo.IsLoopFree = BF.isLoopFree();
FuncInfo.HotSize = BF.estimateHotSize();
FuncInfo.TotalSize = BF.estimateSize();
// early stop for large functions
if (FuncInfo.NumInstrs > 500) {
return false;
}

FuncInfo.IsLoopFree = BF.isLoopFree();
if (!FuncInfo.IsLoopFree) {
auto &BLI = BF.getLoopInfo();
FuncInfo.NumLoops = BLI.OuterLoops;
FuncInfo.MaxLoopDepth = BLI.MaximumDepth;
}
// early stop for large functions
if (FuncInfo.NumInstrs > 500) {
return false;
}

FuncInfo.HotSize = BF.estimateHotSize();
FuncInfo.TotalSize = BF.estimateSize();
FuncInfo.Score = BF.getFunctionScore();

checkInstr(BC, BF, FuncInfo);

// register analysis
BinaryBasicBlock &EntryBB = BF.front();
assert(EntryBB.isEntryPoint() && "Weird, this block should be the entry block!");
assert(EntryBB.isEntryPoint() && "Weird, this should be the entry block!");

dbgs() << "\t EntryBB offset: " << EntryBB.getInputOffset() << "\n";
auto *FirstNonPseudo = EntryBB.getFirstNonPseudoInstr();
if (!FirstNonPseudo) {
return false;
}
dbgs() << "\t " << BC.InstPrinter->getOpcodeName(FirstNonPseudo->getOpcode()) << "\n";

dbgs() << "\t [DefIn at entry point]\n\t ";
DEBUG(dbgs() << "\t [DefIn]\n\t ");
auto LiveInBV = *(DInfo.getLivenessAnalysis().getStateAt(FirstNonPseudo));
LiveInBV &= DefaultDefInMask;
getRegNameFromBitVec(LiveInBV, FuncInfo.DefIn, BC);
getRegNameFromBitVec(BC, LiveInBV, &FuncInfo.DefIn);

outs() << "\t [LiveOut at return point]\n\t ";
DEBUG(dbgs() << "\t [LiveOut]\n\t ");
auto LiveOutBV = RA.getFunctionClobberList(&BF);
LiveOutBV &= DefaultLiveOutMask;
getRegNameFromBitVec(LiveOutBV, FuncInfo.LiveOut, BC);

checkInstr(BC, BF, FuncInfo);
getRegNameFromBitVec(BC, LiveOutBV, &FuncInfo.LiveOut);

outs() << " STOKE-INFO: end function \n";
return true;
Expand All @@ -152,14 +146,14 @@ void StokeInfo::runOnFunctions(
if (!opts::StokeOutputDataFilename.empty()) {
Outfile.open(opts::StokeOutputDataFilename);
} else {
outs() << "STOKE-INFO: output file is required\n";
errs() << "STOKE-INFO: output file is required\n";
return;
}

// check some context meta data
outs() << "\tTarget: " << BC.TheTarget->getName() << "\n";
outs() << "\tTripleName " << BC.TripleName << "\n";
outs() << "\tgetNumRegs " << BC.MRI->getNumRegs() << "\n";
DEBUG(dbgs() << "\tTarget: " << BC.TheTarget->getName() << "\n");
DEBUG(dbgs() << "\tTripleName " << BC.TripleName << "\n");
DEBUG(dbgs() << "\tgetNumRegs " << BC.MRI->getNumRegs() << "\n");

auto CG = buildCallGraph(BC, BFs);
RegAnalysis RA(BC, BFs, CG);
Expand All @@ -173,8 +167,8 @@ void StokeInfo::runOnFunctions(
BC.MIA->getDefaultDefIn(DefaultDefInMask, *BC.MRI);
BC.MIA->getDefaultLiveOut(DefaultLiveOutMask, *BC.MRI);

dumpRegNameFromBitVec(DefaultDefInMask, BC);
dumpRegNameFromBitVec(DefaultLiveOutMask, BC);
getRegNameFromBitVec(BC, DefaultDefInMask);
getRegNameFromBitVec(BC, DefaultLiveOutMask);

StokeFuncInfo FuncInfo;
// analyze all functions
Expand Down
27 changes: 21 additions & 6 deletions bolt/Passes/StokeInfo.h
Expand Up @@ -44,11 +44,13 @@ struct StokeFuncInfo {
unsigned MaxLoopDepth;
uint64_t HotSize;
uint64_t TotalSize;
uint64_t Score;
bool HasCall;
std::set<std::string> DefIn;
std::set<std::string> LiveOut;
bool HeapOut;
bool StackOut;
bool HasRipAddr;
bool Omitted;

StokeFuncInfo() {
Expand All @@ -60,7 +62,14 @@ struct StokeFuncInfo {
Offset = Size = NumInstrs = 0;
NumLoops = MaxLoopDepth = 0;
HotSize = TotalSize = 0;
IsLoopFree = HasCall = HeapOut = StackOut = Omitted = false;
Score = 0;
IsLoopFree
= HasCall
= HeapOut
= StackOut
= HasRipAddr
= Omitted
= false;
DefIn.clear();
LiveOut.clear();
}
Expand All @@ -71,8 +80,11 @@ struct StokeFuncInfo {
<< "FuncName,Offset,Size,NumInstrs,"
<< "IsLoopFree,NumLoops,MaxLoopDepth,"
<< "HotSize,TotalSize,"
<< "Score,"
<< "HasCall,"
<< "DefIn,LiveOut,HeapOut,StackOut,Omitted\n";
<< "DefIn,LiveOut,HeapOut,StackOut,"
<< "HasRipAddr,"
<< "Omitted\n";
}
}

Expand All @@ -82,15 +94,18 @@ struct StokeFuncInfo {
<< FuncName << "," << Offset << "," << Size << "," << NumInstrs << ","
<< IsLoopFree << "," << NumLoops << "," << MaxLoopDepth << ","
<< HotSize << "," << TotalSize << ","
<< HasCall << ",{ ";
<< Score << ","
<< HasCall << ",\"{ ";
for (auto s : DefIn) {
Outfile << s << " ";
Outfile << "%" << s << " ";
}
Outfile << "},{ ";
Outfile << "}\",\"{ ";
for (auto s : LiveOut) {
Outfile << s << " ";
}
Outfile << "}," << HeapOut << "," << StackOut << "," << Omitted << "\n";
Outfile << "}\"," << HeapOut << "," << StackOut << ","
<< HasRipAddr << ","
<< Omitted << "\n";
}
}
};
Expand Down

0 comments on commit 70bad8d

Please sign in to comment.