/* * Copyright 2002-2019 Intel Corporation. * * This software is provided to you as Sample Source Code as defined in the accompanying * End User License Agreement for the Intel(R) Software Development Products ("Agreement") * section 1.L. * * This software and the related documents are provided as is, with no express or implied * warranties, other than those that are expressly stated in the License. */ /* ===================================================================== */ /* Tweaked Muth's catmix.C to make extmix.C. An ISA extension profiler */ /* ===================================================================== */ /*! @file * This file contains a static and dynamic instruction extension mix profiler */ #include "pin.H" #include #include #include #include using std::list; using std::ofstream; using std::cerr; using std::string; using std::endl; /* ===================================================================== */ /* Commandline Switches */ /* ===================================================================== */ KNOB KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool", "o", "extmix.out", "specify profile file name"); KNOB KnobProfilePredicated(KNOB_MODE_WRITEONCE, "pintool", "p", "0", "enable accurate profiling for predicated instructions"); KNOB KnobProfileStaticOnly(KNOB_MODE_WRITEONCE, "pintool", "s", "0", "terminate after collection of static profile for main image"); KNOB KnobNoSharedLibs(KNOB_MODE_WRITEONCE, "pintool", "no_shared_libs", "0", "do not instrument shared libraries"); /* ===================================================================== */ /* Print Help Message */ /* ===================================================================== */ INT32 Usage() { cerr << "This pin tool computes static and dynamic instruction family (=extension) mix profile\n" "\n"; cerr << KNOB_BASE::StringKnobSummary() << endl; return -1; } /* ===================================================================== */ /* Global Variables */ /* ===================================================================== */ const UINT32 MAX_INDEX = 64; typedef UINT64 COUNTER; /* zero initialized */ typedef struct { COUNTER unpredicated[MAX_INDEX]; COUNTER predicated[MAX_INDEX]; COUNTER predicated_true[MAX_INDEX]; }STATS; STATS GlobalStatsStatic; STATS GlobalStatsDynamic; class BBLSTATS { public: BBLSTATS(UINT16 * stats) : _stats(stats),_counter(0) {}; const UINT16 * _stats; COUNTER _counter; }; list statsList; /* ===================================================================== */ VOID ComputeGlobalStats() { // We have the count for each bbl and its stats, compute the summary for (list::iterator bi = statsList.begin(); bi != statsList.end(); bi++) { for (const UINT16 * stats = (*bi)->_stats; *stats; stats++) { GlobalStatsDynamic.unpredicated[*stats] += (*bi)->_counter; } } } /* ===================================================================== */ UINT16 INS_GetStatsIndex(INS ins) { if( INS_IsPredicated(ins) ) return MAX_INDEX + INS_Extension(ins); else return INS_Extension(ins); } /* ===================================================================== */ VOID docount(COUNTER * counter) { (*counter)++; } /* ===================================================================== */ VOID Trace(TRACE trace, VOID *v) { if ( KnobNoSharedLibs.Value() && IMG_Type(SEC_Img(RTN_Sec(TRACE_Rtn(trace)))) == IMG_TYPE_SHAREDLIB) return; const BOOL accurate_handling_of_predicates = KnobProfilePredicated.Value(); for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { // Summarize the stats for the bbl in a 0 terminated list // This is done at instrumentation time UINT16 * stats = new UINT16[BBL_NumIns(bbl) + 1]; INT32 index = 0; for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) { // Count the number of times a predicated instruction is actually executed // this is expensive and hence disabled by default if( INS_IsPredicated(ins) && accurate_handling_of_predicates ) { INS_InsertPredicatedCall(ins, IPOINT_BEFORE, AFUNPTR(docount), IARG_PTR, &(GlobalStatsDynamic.predicated_true[INS_Extension(ins)]), IARG_END); } stats[index++] = INS_GetStatsIndex(ins); } stats[index] = 0; // Insert instrumentation to count the number of times the bbl is executed BBLSTATS * bblstats = new BBLSTATS(stats); INS_InsertCall(BBL_InsHead(bbl), IPOINT_BEFORE, AFUNPTR(docount), IARG_PTR, &(bblstats->_counter), IARG_END); // Remember the counter and stats so we can compute a summary at the end statsList.push_back(bblstats); } } /* ===================================================================== */ VOID DumpStats(ofstream& out, STATS& stats, const string& title) { out << "#\n" "# " << title << "\n" "#\n" "#num extension count-unpredicated count-predicated count-predicated-true\n" "#\n"; for ( UINT32 i = 0; i < MAX_INDEX; i++) { if( stats.unpredicated[i] == 0 && stats.predicated[i] == 0 ) continue; out << decstr(i,3) << " " << ljstr(EXTENSION_StringShort(i),15) << decstr( stats.unpredicated[i],12) << decstr( stats.predicated[i],12) << decstr( stats.predicated_true[i],12) << endl; } } /* ===================================================================== */ static std::ofstream* out = 0; VOID Fini(int, VOID * v) { DumpStats(*out, GlobalStatsStatic, "static counts"); *out << endl; ComputeGlobalStats(); DumpStats(*out, GlobalStatsDynamic, "dynamic counts"); *out << "# eof" << endl; out->close(); } /* ===================================================================== */ VOID Image(IMG img, VOID * v) { for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { RTN_Open(rtn); for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins)) { if( INS_IsPredicated(ins) ) GlobalStatsStatic.predicated[ INS_Extension(ins) ]++; else GlobalStatsStatic.unpredicated[ INS_Extension(ins) ]++; } RTN_Close(rtn); } } if( KnobProfileStaticOnly.Value() ) { Fini(0,0); exit(0); } } /* ===================================================================== */ /* Main */ /* ===================================================================== */ int main(int argc, CHAR *argv[]) { PIN_InitSymbols(); if( PIN_Init(argc,argv) ) { return Usage(); } out = new std::ofstream(KnobOutputFile.Value().c_str()); TRACE_AddInstrumentFunction(Trace, 0); PIN_AddFiniFunction(Fini, 0); IMG_AddInstrumentFunction(Image, 0); // Never returns PIN_StartProgram(); return 0; } /* ===================================================================== */ /* eof */ /* ===================================================================== */