minix/minix/llvm/passes/include/common/qprof_common.h
David van Moolenbroek 3e457fe321 Import magic pass from llvm-apps
Change-Id: I19535b913b50f2ff24aeb80ddefc92e305c31fe8
2015-09-17 13:57:53 +00:00

570 lines
18 KiB
C++

#ifndef _QPROF_COMMON_H
#define _QPROF_COMMON_H
#include <cstdlib>
#include <common/util/stdlib.h>
#define QPROF_SEP ","
#define QPROF_SEP2 ":"
#define QPROF_SEP3 "|"
#define QPROF_DECLARE_LL_SITESTACKS_OPT(P, VAR) \
static cl::opt<std::string> \
VAR(#P "-ll-sitestacks", \
cl::desc("Specify all the long-lived sitestacks on a per-task basis in qprof format"), \
cl::init(""), cl::NotHidden, cl::ValueRequired)
#define QPROF_DECLARE_DEEPEST_LL_LOOPS_OPT(P, VAR) \
static cl::opt<std::string> \
VAR(#P "-deepest-ll-loops", \
cl::desc("Specify all the deepest long-lived loops on a per-task basis in qprof format"), \
cl::init(""), cl::NotHidden, cl::ValueRequired)
#define QPROF_DECLARE_DEEPEST_LL_LIBS_OPT(P, VAR) \
static cl::opt<std::string> \
VAR(#P "-deepest-ll-libs", \
cl::desc("Specify all the deepest long-lived loop lib calls on a per-task basis in qprof format"), \
cl::init(""), cl::NotHidden, cl::ValueRequired)
#define QPROF_DECLARE_TASK_CLASSES_OPT(P, VAR) \
static cl::opt<std::string> \
VAR(#P "-task-classes", \
cl::desc("Specify all the task classes in qprof format"), \
cl::init(""), cl::NotHidden, cl::ValueRequired)
#define QPROF_DECLARE_ALL_OPTS(P, VAR1, VAR2, VAR3, VAR4) \
QPROF_DECLARE_LL_SITESTACKS_OPT(P, VAR1); \
QPROF_DECLARE_DEEPEST_LL_LOOPS_OPT(P, VAR2); \
QPROF_DECLARE_DEEPEST_LL_LIBS_OPT(P, VAR3); \
QPROF_DECLARE_TASK_CLASSES_OPT(P, VAR4) \
using namespace llvm;
namespace llvm {
class QProfSite {
public:
static QProfSite* get(Module &M, int taskClassID, int taskSiteID, std::string moduleName, int lineNum, std::string functionName, std::string siteName, std::string siteFuncName, int siteDepth, int lib, unsigned long libFlags, bool refreshSite=true);
static QProfSite* getFromString(Module &M, int taskClassID, int taskSiteID, std::string &siteString, bool refreshSite=true);
static std::vector<QProfSite*> getFromSitesString(Module &M, std::string &sitesString, bool refreshSites=true);
void refresh(Module &M);
std::string toString();
bool isLoop();
bool isFunction();
bool isCallsite();
bool isLibCallsite();
bool equals(QProfSite *other);
int taskClassID;
int taskSiteID;
std::string moduleName;
int lineNum;
std::string functionName;
std::string siteName;
std::string siteFuncName;
unsigned long libFlags;
Function *function;
Function *siteFunction;
Instruction *siteInstruction;
private:
QProfSite() {}
int siteDepth;
int lib;
};
class QProfConf {
public:
static QProfConf* get(Module &M, std::string *llSitestacks, std::string *deepestLLLoops, std::string *deepestLLLibs, std::string *taskClasses, bool refreshSites=true);
std::map<int, std::vector<QProfSite*> > getTaskClassLLSitestacks();
std::map<int, QProfSite*> getTaskClassDeepestLLLoops();
std::map<int, std::vector<QProfSite*> > getTaskClassDeepestLLLibs();
int getNumTaskClasses();
int getNumLLTaskClasses();
int getNumLLBlockExtTaskClasses();
int getNumLLBlockIntTaskClasses();
int getNumLLBlockExtLibs();
int getNumLLBlockIntLibs();
std::vector<QProfSite*> getLLFunctions();
std::vector<QProfSite*> getDeepestLLLoops();
std::vector<QProfSite*> getDeepestLLLibs();
bool lookupTaskClassLibFlags(int taskClassID, int *libFlags);
void mergeTaskClassLLSitestacks(int taskClassID, int otherTaskClassID);
void mergeTaskClassDeepestLLLoops(int taskClassID, int otherTaskClassID);
void mergeTaskClassDeepestLLLibs(int taskClassID, int otherTaskClassID);
void mergeTaskClassPair(int taskClassID, int otherTaskClassID);
void mergeAllTaskClassesWithSameDeepestLLLoops();
void print(raw_ostream &O);
void printSiteList(raw_ostream &O, std::vector<QProfSite*> &list);
private:
QProfConf() {}
static std::map<int, std::vector<QProfSite*> > parseTaskClassSiteList(Module &M, std::string &str, bool refreshSites=true);
static std::map<int, QProfSite*> parseTaskClassSite(Module &M, std::string &str, bool refreshSites=true);
static std::vector<int> parseIntList(std::string &str);
std::map<int, std::vector<QProfSite*> > taskClassLLSitestacks;
std::map<int, QProfSite*> taskClassDeepestLLLoops;
std::map<int, std::vector<QProfSite*> > taskClassDeepestLLLibs;
int numTaskClasses;
int numLLTaskClasses;
int numLLBlockExtTaskClasses;
int numLLBlockIntTaskClasses;
int numLLBlockExtLibs;
int numLLBlockIntLibs;
};
static int stringRefToInt(StringRef &ref)
{
return atoi(ref.str().c_str());
}
inline QProfSite* QProfSite::get(Module &M, int taskClassID, int taskSiteID,
std::string moduleName, int lineNum, std::string functionName,
std::string siteName, std::string siteFuncName, int siteDepth, int lib,
unsigned long libFlags, bool refreshSite)
{
QProfSite *site = new QProfSite();
site->taskClassID = taskClassID;
site->taskSiteID = taskSiteID;
site->moduleName = moduleName;
site->lineNum = lineNum;
site->functionName = functionName;
site->siteName = siteName;
site->siteFuncName = siteFuncName;
site->siteDepth = siteDepth;
site->lib = lib;
site->libFlags = libFlags;
site->function = NULL;
site->siteFunction = NULL;
site->siteInstruction = NULL;
if (refreshSite) {
site->refresh(M);
}
return site;
}
inline QProfSite* QProfSite::getFromString(Module &M, int taskClassID, int taskSiteID,
std::string &siteString, bool refreshSite)
{
StringRef ref(siteString);
SmallVector< StringRef, 3 > tokenVector;
if (!siteString.compare("")) {
return NULL;
}
ref.split(tokenVector, QPROF_SEP3);
assert(tokenVector.size() == 8);
return get(M, taskClassID, taskSiteID, tokenVector[0], stringRefToInt(tokenVector[1]),
tokenVector[2], tokenVector[3], tokenVector[4],
stringRefToInt(tokenVector[5]), stringRefToInt(tokenVector[6]),
stringRefToInt(tokenVector[7]), refreshSite);
}
inline std::vector<QProfSite*> QProfSite::getFromSitesString(Module &M,
std::string &sitesString, bool refreshSites)
{
unsigned i;
int taskClassID;
std::vector<QProfSite*> sites;
StringRef ref(sitesString);
SmallVector< StringRef, 3 > tokenVector;
if (!sitesString.compare("")) {
return sites;
}
ref.split(tokenVector, QPROF_SEP2);
assert(tokenVector.size() > 1);
taskClassID = stringRefToInt(tokenVector[0]);
for (i=1;i<tokenVector.size();i++) {
std::string token = tokenVector[i].str();
QProfSite *site = QProfSite::getFromString(M, taskClassID, i, token,
refreshSites);
sites.push_back(site);
}
return sites;
}
inline void QProfSite::refresh(Module &M)
{
BasicBlock *siteBB = NULL;
function = NULL;
siteFunction = NULL;
siteInstruction = NULL;
function = M.getFunction(functionName);
siteFunction = M.getFunction(siteFuncName);
if (!siteFunction) {
errs() << "Function " << siteFuncName << " not found. Invalid qprof profiling data?\n";
}
assert(siteFunction);
for (Function::iterator BB = siteFunction->begin(),
e = siteFunction->end(); BB != e; ++BB) {
if (!BB->getName().compare(siteName)) {
siteBB = BB;
break;
}
}
assert(siteBB);
if (isCallsite()) {
for (BasicBlock::iterator it = siteBB->begin(); it != siteBB->end(); ++it) {
CallSite CS(it);
if (CS.getInstruction() && CS.getCalledFunction() == function) {
siteInstruction = it;
break;
}
}
assert(siteInstruction && "Invalid qprof callsite?");
}
else {
siteInstruction = &siteBB->front();
}
}
inline std::string QProfSite::toString()
{
std::string str;
raw_string_ostream ostream(str);
ostream << taskClassID << QPROF_SEP3 << taskSiteID << QPROF_SEP3 << moduleName << QPROF_SEP3 << lineNum << QPROF_SEP3 << functionName << QPROF_SEP3 << siteName << QPROF_SEP3 << siteFuncName << QPROF_SEP3 << siteDepth << QPROF_SEP3 << lib << QPROF_SEP3 << libFlags;
ostream.flush();
return str;
}
inline bool QProfSite::isLoop()
{
return siteDepth > 0;
}
inline bool QProfSite::isFunction()
{
return !isLoop() && !isCallsite();
}
inline bool QProfSite::isCallsite()
{
return isLibCallsite();
}
inline bool QProfSite::isLibCallsite()
{
return lib != 0;
}
inline bool QProfSite::equals(QProfSite *other)
{
if (lineNum != other->lineNum) {
return false;
}
if (libFlags != other->libFlags) {
return false;
}
if (moduleName.compare(other->moduleName)) {
return false;
}
if (functionName.compare(other->functionName)) {
return false;
}
if (siteName.compare(other->siteName)) {
return false;
}
if (siteFuncName.compare(other->siteFuncName)) {
return false;
}
return true;
}
inline QProfConf* QProfConf::get(Module &M, std::string *llSitestacks,
std::string *deepestLLLoops, std::string *deepestLLLibs,
std::string *taskClasses, bool refreshSites)
{
std::vector<int> intValues;
QProfConf *conf = new QProfConf();
if (llSitestacks) {
conf->taskClassLLSitestacks = parseTaskClassSiteList(M,
*llSitestacks, refreshSites);
}
if (deepestLLLoops) {
conf->taskClassDeepestLLLoops = parseTaskClassSite(M,
*deepestLLLoops, refreshSites);
}
if (deepestLLLibs) {
conf->taskClassDeepestLLLibs = parseTaskClassSiteList(M,
*deepestLLLibs, refreshSites);
}
if (taskClasses) {
intValues = parseIntList(*taskClasses);
}
if (intValues.size() > 0) {
assert(intValues.size() == 6);
conf->numTaskClasses = intValues[0];
conf->numLLTaskClasses = intValues[1];
conf->numLLBlockExtTaskClasses = intValues[2];
conf->numLLBlockIntTaskClasses = intValues[3];
conf->numLLBlockExtLibs = intValues[4];
conf->numLLBlockIntLibs = intValues[5];
}
else {
conf->numTaskClasses = 0;
conf->numLLTaskClasses = 0;
conf->numLLBlockExtTaskClasses = 0;
conf->numLLBlockIntTaskClasses = 0;
conf->numLLBlockExtLibs = 0;
conf->numLLBlockIntLibs = 0;
}
return conf;
}
inline std::map<int, std::vector<QProfSite*> > QProfConf::getTaskClassLLSitestacks()
{
return taskClassLLSitestacks;
}
inline std::map<int, QProfSite*> QProfConf::getTaskClassDeepestLLLoops()
{
return taskClassDeepestLLLoops;
}
inline std::map<int, std::vector<QProfSite*> > QProfConf::getTaskClassDeepestLLLibs()
{
return taskClassDeepestLLLibs;
}
inline int QProfConf::getNumTaskClasses()
{
return numTaskClasses;
}
inline int QProfConf::getNumLLTaskClasses()
{
return numLLTaskClasses;
}
inline int QProfConf::getNumLLBlockExtTaskClasses()
{
return numLLBlockExtTaskClasses;
}
inline int QProfConf::getNumLLBlockIntTaskClasses()
{
return numLLBlockIntTaskClasses;
}
inline int QProfConf::getNumLLBlockExtLibs()
{
return numLLBlockExtLibs;
}
inline int QProfConf::getNumLLBlockIntLibs()
{
return numLLBlockIntLibs;
}
inline std::vector<QProfSite*> QProfConf::getLLFunctions()
{
std::vector<QProfSite*> sites;
std::map<int, std::vector<QProfSite*> >::iterator it;
it = taskClassLLSitestacks.begin();
for (; it != taskClassLLSitestacks.end(); it++) {
std::vector<QProfSite*> *siteVector = &it->second;
for (unsigned i=0;i<siteVector->size();i++) {
QProfSite* site = (*siteVector)[i];
if (site->isFunction()) {
sites.push_back((*siteVector)[i]);
}
}
}
return sites;
}
inline std::vector<QProfSite*> QProfConf::getDeepestLLLoops()
{
std::vector<QProfSite*> sites;
std::map<int, QProfSite*>::iterator it;
it = taskClassDeepestLLLoops.begin();
for (; it != taskClassDeepestLLLoops.end(); it++) {
sites.push_back(it->second);
}
return sites;
}
inline std::vector<QProfSite*> QProfConf::getDeepestLLLibs()
{
std::vector<QProfSite*> sites;
std::map<int, std::vector<QProfSite*> >::iterator it;
it = taskClassDeepestLLLibs.begin();
for (; it != taskClassDeepestLLLibs.end(); it++) {
std::vector<QProfSite*> *siteVector = &it->second;
for (unsigned i=0;i<siteVector->size();i++) {
sites.push_back((*siteVector)[i]);
}
}
return sites;
}
inline bool QProfConf::lookupTaskClassLibFlags(int taskClassID, int *libFlags)
{
bool found = false;
std::vector<QProfSite*> deepestLLLibs = getDeepestLLLibs();
*libFlags = 0;
for (unsigned i=0;i<deepestLLLibs.size();i++) {
QProfSite *site = deepestLLLibs[i];
if (site->taskClassID == taskClassID) {
*libFlags |= site->libFlags;
found = true;
}
}
return found;
}
inline void QProfConf::mergeTaskClassLLSitestacks(int taskClassID, int otherTaskClassID)
{
size_t erased = taskClassLLSitestacks.erase(otherTaskClassID);
assert(erased == 1);
}
inline void QProfConf::mergeTaskClassDeepestLLLoops(int taskClassID, int otherTaskClassID)
{
size_t erased = taskClassDeepestLLLoops.erase(otherTaskClassID);
assert(erased == 1);
}
inline void QProfConf::mergeTaskClassDeepestLLLibs(int taskClassID, int otherTaskClassID)
{
size_t erased = taskClassDeepestLLLibs.erase(otherTaskClassID);
assert(erased == 1);
}
inline void QProfConf::mergeTaskClassPair(int taskClassID,
int otherTaskClassID)
{
int libFlags;
mergeTaskClassLLSitestacks(taskClassID, otherTaskClassID);
mergeTaskClassDeepestLLLoops(taskClassID, otherTaskClassID);
mergeTaskClassDeepestLLLibs(taskClassID, otherTaskClassID);
numTaskClasses--;
if (lookupTaskClassLibFlags(taskClassID, &libFlags)) {
numLLTaskClasses--;
if (libFlags & _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)) {
numLLBlockExtTaskClasses--;
}
else {
numLLBlockIntTaskClasses--;
}
}
}
inline void QProfConf::mergeAllTaskClassesWithSameDeepestLLLoops()
{
std::vector<QProfSite*> deepestLLLoops = getDeepestLLLoops();
std::vector<std::pair<QProfSite*, QProfSite*> > loopPairs;
for (unsigned i=0;i<deepestLLLoops.size();i++) {
QProfSite *site = deepestLLLoops[i];
for (unsigned j=0;j<i;j++) {
if (site->equals(deepestLLLoops[j])) {
loopPairs.push_back(std::pair<QProfSite*, QProfSite*>(site, deepestLLLoops[j]));
}
}
}
for (unsigned i=0;i<loopPairs.size();i++) {
int taskClassID = loopPairs[i].first->taskClassID;
int otherTaskClassID = loopPairs[i].second->taskClassID;
mergeTaskClassPair(taskClassID, otherTaskClassID);
}
}
inline void QProfConf::print(raw_ostream &O)
{
std::vector<QProfSite*> list;
O << "*** QProfConf:\n";
O << " - numTaskClasses=" << getNumTaskClasses() << "\n";
O << " - numLLTaskClasses=" << getNumLLTaskClasses() << "\n";
O << " - numLLBlockExtTaskClasses=" << getNumLLBlockExtTaskClasses() << "\n";
O << " - numLLBlockIntTaskClasses=" << getNumLLBlockIntTaskClasses() << "\n";
O << " - numLLBlockExtLibs=" << getNumLLBlockExtLibs() << "\n";
O << " - numLLBlockIntLibs=" << getNumLLBlockIntLibs() << "\n";
list = getLLFunctions();
O << " - LLFunctions="; printSiteList(O, list); O << "\n";
list = getDeepestLLLoops();
O << " - deepestLLLoops="; printSiteList(O, list); O << "\n";
list = getDeepestLLLibs();
O << " - deepestLLLibs="; printSiteList(O, list); O << "\n";
}
inline void QProfConf::printSiteList(raw_ostream &O, std::vector<QProfSite*> &list)
{
for (std::vector<QProfSite*>::iterator it = list.begin(); it != list.end(); it++) {
QProfSite* site = *it;
if (it != list.begin()) {
O << ", ";
}
O << "{ ";
O << site->toString();
O << " }";
}
}
inline std::map<int, std::vector<QProfSite*> > QProfConf::parseTaskClassSiteList(Module &M,
std::string &str, bool refreshSites)
{
std::map<int, std::vector<QProfSite*> > siteListMap;
StringRef ref(str);
SmallVector< StringRef, 3 > tokenVector;
if (!str.compare("")) {
return siteListMap;
}
ref.split(tokenVector, QPROF_SEP);
for (unsigned i=0;i<tokenVector.size();i++) {
std::string token = tokenVector[i].str();
std::vector<QProfSite*> sites = QProfSite::getFromSitesString(M,
token, refreshSites);
if (sites.size() > 0) {
int taskClassID = sites[0]->taskClassID;
siteListMap.insert(std::pair<int, std::vector<QProfSite*> >(taskClassID,
sites));
}
}
return siteListMap;
}
inline std::map<int, QProfSite*> QProfConf::parseTaskClassSite(Module &M,
std::string &str, bool refreshSites)
{
std::map<int, std::vector<QProfSite*> >::iterator it;
std::map<int, std::vector<QProfSite*> > siteListMap =
parseTaskClassSiteList(M, str, refreshSites);
std::map<int, QProfSite*> siteMap;
for (it=siteListMap.begin();it!=siteListMap.end();it++) {
std::vector<QProfSite*> list = it->second;
assert(list.size() == 1);
siteMap.insert(std::pair<int, QProfSite*>(it->first, list[0]));
}
return siteMap;
}
inline std::vector<int> QProfConf::parseIntList(std::string &str)
{
std::vector<int> intValues;
StringRef ref(str);
SmallVector< StringRef, 3 > tokenVector;
if (!str.compare("")) {
return intValues;
}
ref.split(tokenVector, QPROF_SEP);
for (unsigned i=0;i<tokenVector.size();i++) {
intValues.push_back(stringRefToInt(tokenVector[i]));
}
return intValues;
}
}
#endif /* _QPROF_COMMON_H */