18 #include <unordered_set>
20 #include <unordered_map>
26 #define USE_TREE_BASED_FOR_DATA_CENTRIC
27 #define USE_TREE_WITH_ADDR
32 #define THREAD_MAX (1024)
34 #define GEN_REG_NUM (16)
35 #define GEN_REG_LEN (8)
36 #define X87_REG_NUM (8)
37 #define X87_REG_LEN (10)
38 #define SIMD_REG_NUM (16)
39 #define SIMD_REG_LEN (32)
41 #define SAME_RATE (0.1)
42 #define SAME_RECORD_LIMIT (0)
43 #define RED_RATE (0.9)
44 #define APPROX_RATE (0.01)
46 #define ARRAY_UPDATE_THRESHOLD(a) (a / 4)
47 #define MAKE_CONTEXT_PAIR(a, b) (((uint64_t)(a) << 32) | ((uint64_t)(b)))
49 #define ARRAY_ANALYSIS_FN_NAME "Analyze_this_array"
50 #define REG_ANALYSIS_FN_NAME "Analyze_regs"
54 list<uint32_t> indexes;
93 PIN_ERROR(
"Pin tool to gather calling context on each load and store.\n" + KNOB_BASE::StringKnobSummary() +
"\n");
104 char* envPath = getenv(
"CCTLIB_CLIENT_OUTPUT_FILE");
108 snprintf(name,
sizeof(name),
"%s", envPath);
111 gethostname(name + strlen(name),
MAX_FILE_PATH - strlen(name));
112 pid_t pid = getpid();
113 sprintf(name + strlen(name),
"%d", pid);
114 cerr <<
"\n Creating log file at:" << name <<
"\n";
119 for (
int i = 0; i < argc; i++) {
131 unordered_map<uint32_t, list<IntraRegsRed>>::iterator it;
132 it =
regsRed[threadId].find(ctxt);
133 if (it ==
regsRed[threadId].end()) {
134 list<IntraRegsRed> newlist;
135 newlist.push_back(redPair);
136 regsRed[threadId].insert(std::pair<uint32_t, list<IntraRegsRed>>(ctxt, newlist));
138 it->second.push_back(redPair);
143 unordered_map<string, list<IntraRedRecord>>::iterator it;
146 list<IntraRedRecord> newlist;
147 newlist.push_back(redPair);
148 arrayDataRed[threadId].insert(std::pair<
string, list<IntraRedRecord>>(name, newlist));
150 it->second.push_back(redPair);
159 genRegs = (UINT8**)malloc(
GEN_REG_NUM *
sizeof(UINT8*));
161 genRegs[i] = (UINT8*)malloc(
GEN_REG_LEN *
sizeof(UINT8));
164 PIN_GetContextRegval(ctxt, LEVEL_BASE::REG_RAX, genRegs[0]);
165 PIN_GetContextRegval(ctxt, LEVEL_BASE::REG_RBX, genRegs[1]);
166 PIN_GetContextRegval(ctxt, LEVEL_BASE::REG_RCX, genRegs[2]);
167 PIN_GetContextRegval(ctxt, LEVEL_BASE::REG_RDX, genRegs[3]);
169 PIN_GetContextRegval(ctxt, LEVEL_BASE::REG_RBP, genRegs[4]);
170 PIN_GetContextRegval(ctxt, LEVEL_BASE::REG_RDI, genRegs[5]);
171 PIN_GetContextRegval(ctxt, LEVEL_BASE::REG_RSI, genRegs[6]);
172 PIN_GetContextRegval(ctxt, LEVEL_BASE::REG_RSP, genRegs[7]);
174 PIN_GetContextRegval(ctxt, LEVEL_BASE::REG_R8, genRegs[8]);
175 PIN_GetContextRegval(ctxt, LEVEL_BASE::REG_R9, genRegs[9]);
176 PIN_GetContextRegval(ctxt, LEVEL_BASE::REG_R10, genRegs[10]);
177 PIN_GetContextRegval(ctxt, LEVEL_BASE::REG_R11, genRegs[11]);
178 PIN_GetContextRegval(ctxt, LEVEL_BASE::REG_R12, genRegs[12]);
179 PIN_GetContextRegval(ctxt, LEVEL_BASE::REG_R13, genRegs[13]);
180 PIN_GetContextRegval(ctxt, LEVEL_BASE::REG_R14, genRegs[14]);
181 PIN_GetContextRegval(ctxt, LEVEL_BASE::REG_R15, genRegs[15]);
185 x87Regs = (UINT8**)malloc(
X87_REG_NUM *
sizeof(UINT8*));
187 x87Regs[i] = (UINT8*)malloc(
X87_REG_LEN *
sizeof(UINT8));
190 PIN_GetContextRegval(ctxt, REG_ST0, x87Regs[0]);
191 PIN_GetContextRegval(ctxt, REG_ST1, x87Regs[1]);
192 PIN_GetContextRegval(ctxt, REG_ST2, x87Regs[2]);
193 PIN_GetContextRegval(ctxt, REG_ST3, x87Regs[3]);
194 PIN_GetContextRegval(ctxt, REG_ST4, x87Regs[4]);
195 PIN_GetContextRegval(ctxt, REG_ST5, x87Regs[5]);
196 PIN_GetContextRegval(ctxt, REG_ST6, x87Regs[6]);
197 PIN_GetContextRegval(ctxt, REG_ST7, x87Regs[7]);
201 simdRegs = (UINT8**)malloc(
SIMD_REG_NUM *
sizeof(UINT8*));
203 simdRegs[i] = (UINT8*)malloc(
SIMD_REG_LEN *
sizeof(UINT8));
206 PIN_GetContextRegval(ctxt, REG_YMM0, simdRegs[0]);
207 PIN_GetContextRegval(ctxt, REG_YMM1, simdRegs[1]);
208 PIN_GetContextRegval(ctxt, REG_YMM2, simdRegs[2]);
209 PIN_GetContextRegval(ctxt, REG_YMM3, simdRegs[3]);
210 PIN_GetContextRegval(ctxt, REG_YMM4, simdRegs[4]);
211 PIN_GetContextRegval(ctxt, REG_YMM5, simdRegs[5]);
212 PIN_GetContextRegval(ctxt, REG_YMM6, simdRegs[6]);
213 PIN_GetContextRegval(ctxt, REG_YMM7, simdRegs[7]);
214 PIN_GetContextRegval(ctxt, REG_YMM8, simdRegs[8]);
215 PIN_GetContextRegval(ctxt, REG_YMM9, simdRegs[9]);
216 PIN_GetContextRegval(ctxt, REG_YMM10, simdRegs[10]);
217 PIN_GetContextRegval(ctxt, REG_YMM11, simdRegs[11]);
218 PIN_GetContextRegval(ctxt, REG_YMM12, simdRegs[12]);
219 PIN_GetContextRegval(ctxt, REG_YMM13, simdRegs[13]);
220 PIN_GetContextRegval(ctxt, REG_YMM14, simdRegs[14]);
221 PIN_GetContextRegval(ctxt, REG_YMM15, simdRegs[15]);
228 valuesMap[index++] = *(uint64_t*)(genRegs[0]);
231 for (j = 0; j < index; ++j) {
232 if (*(uint64_t*)(genRegs[i]) == valuesMap[j]) {
237 valuesMap[index++] = *(uint64_t*)(genRegs[i]);
245 x87values = (UINT8**)malloc(
X87_REG_NUM *
sizeof(UINT8*));
247 x87values[i] = (UINT8*)malloc(
X87_REG_LEN *
sizeof(UINT8));
250 memcpy(x87values[index++], x87Regs[0],
X87_REG_LEN *
sizeof(UINT8));
252 for (j = 0; j < index; ++j) {
253 if (memcmp(x87values[j], x87Regs[i],
X87_REG_LEN *
sizeof(UINT8)) == 0) {
258 memcpy(x87values[index++], x87Regs[i],
X87_REG_LEN *
sizeof(UINT8));
265 simdValues = (UINT8**)malloc(
SIMD_REG_NUM *
sizeof(UINT8*));
267 simdValues[i] = (UINT8*)malloc(
SIMD_REG_LEN *
sizeof(UINT8));
270 memcpy(simdValues[index++], simdRegs[0],
SIMD_REG_LEN *
sizeof(UINT8));
271 for (
int i = 1; i < 8; ++i) {
272 for (j = 0; j < index; ++j) {
273 if (memcmp(simdValues[j], simdRegs[i],
SIMD_REG_LEN *
sizeof(UINT8)) == 0) {
278 memcpy(simdValues[index++], simdRegs[i],
SIMD_REG_LEN *
sizeof(UINT8));
286 newpair.genRegRed = genRegRate;
287 newpair.x87RegRed = x87RegRate;
288 newpair.simdRegRed = simdRegRate;
294 template <
typename T,
bool isApprox>
296 using MyIterator =
typename unordered_map<T, list<uint32_t>>::iterator;
298 static __attribute__((always_inline))
bool CheckIntraArrayRedundancy(uint64_t begAddr, uint64_t endAddr, uint32_t stride,
IntraRedRecord* newPair) {
299 unordered_map<T, list<uint32_t>> valuesMap;
311 spatialRedIndex.push_back(index);
312 for (mapIt = valuesMap.begin(); mapIt != valuesMap.end(); ++mapIt) {
315 mapIt->second.push_back(index);
319 if (mapIt == valuesMap.end()) {
320 list<uint32_t> newlist;
321 newlist.push_back(index);
322 valuesMap.insert(std::pair<T, list<uint32_t>>(
value, newlist));
325 if (
value == valueLast)
326 spatialRedIndex.push_back(index);
327 mapIt = valuesMap.find(
value);
328 if (mapIt == valuesMap.end()) {
329 list<uint32_t> newlist;
330 newlist.push_back(index);
331 valuesMap.insert(std::pair<T, list<uint32_t>>(
value, newlist));
333 mapIt->second.push_back(index);
340 uint32_t numUniqueValue = valuesMap.size();
341 double redRate = (double)(index - numUniqueValue) / index;
343 for (mapIt = valuesMap.begin(); mapIt != valuesMap.end(); ++mapIt) {
344 if (mapIt->second.size() > index *
SAME_RATE) {
346 newGroup.indexes = mapIt->second;
347 maxList.push_back(newGroup);
351 newPair->redundancy = redRate;
352 newPair->group = maxList;
353 newPair->spatialRedInd = spatialRedIndex;
370 bool hasRedundant =
false;
381 assert(0 &&
"approx inappropriate type size, should not reach here!");
399 assert(0 &&
"unknow element size, should not reach here!");
405 newRecord.curCtxt = curCtxtHandle;
441 for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) {
442 for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) {
443 string rtnName = RTN_Name(rtn);
448 PROTO proto_master = PROTO_Allocate(PIN_PARG(
void), CALLINGSTD_DEFAULT,
449 ARRAY_ANALYSIS_FN_NAME, PIN_PARG(
char*), PIN_PARG(
void*), PIN_PARG(uint32_t), PIN_PARG(uint32_t), PIN_PARG(
bool),
456 IARG_PROTOTYPE, proto_master,
457 IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
458 IARG_FUNCARG_ENTRYPOINT_VALUE, 1,
459 IARG_FUNCARG_ENTRYPOINT_VALUE, 2,
460 IARG_FUNCARG_ENTRYPOINT_VALUE, 3,
461 IARG_FUNCARG_ENTRYPOINT_VALUE, 4,
462 IARG_THREAD_ID, IARG_END);
464 PROTO_Free(proto_master);
467 RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)
CheckRegValues, IARG_CONTEXT, IARG_THREAD_ID, IARG_END);
482 list<uint32_t>::iterator it = inlist.begin();
483 uint32_t tmp = (*it);
484 string indexList =
"[" + to_string(tmp) +
",";
486 while (it != inlist.end()) {
487 if (*it == tmp + 1) {
490 indexList += to_string(tmp) +
"],[" + to_string(*it) +
",";
495 indexList += to_string(tmp) +
"]";
505 fprintf(
gTraceFile,
"\n*************** Intra Array Redundancy of Thread %d ***************\n", threadId);
506 unordered_map<string, list<IntraRedRecord>>::iterator itIntra;
508 fprintf(
gTraceFile,
"========== Selected Dataobjecy Redundancy ==========\n");
510 fprintf(
gTraceFile,
"\nVariable %s: \n", (itIntra->first).c_str());
512 list<IntraRedRecord>::iterator listIt;
513 for (listIt = itIntra->second.begin(); listIt != itIntra->second.end(); ++listIt) {
515 fprintf(
gTraceFile,
"\nRed:%.2f, unique value large index group:\n", (*listIt).redundancy);
516 list<ValueGroup>::iterator groupIt;
518 for (groupIt = (*listIt).group.begin(); groupIt != (*listIt).group.end(); ++groupIt) {
520 fprintf(
gTraceFile,
"Group %d: %s\n", num, indexlist.c_str());
523 fprintf(
gTraceFile,
"redundant spatial indexes:%s\n", indexlist.c_str());
525 fprintf(
gTraceFile,
"\n----------------------------");
528 fprintf(
gTraceFile,
"\n*************** Intra Registers Redundancy of Thread %d ***************\n", threadId);
529 unordered_map<uint32_t, list<IntraRegsRed>>::iterator itIntraReg;
531 fprintf(
gTraceFile,
"========== ==========\n");
532 for (itIntraReg =
regsRed[threadId].begin(); itIntraReg !=
regsRed[threadId].end(); ++itIntraReg) {
535 list<IntraRegsRed>::iterator listItReg;
536 for (listItReg = itIntraReg->second.begin(); listItReg != itIntraReg->second.end(); ++listItReg) {
537 fprintf(
gTraceFile,
"\n general registers redundancy: %.2f\n", (*listItReg).genRegRed);
538 fprintf(
gTraceFile,
"\n X87 registers redundancy: %.2f\n", (*listItReg).x87RegRed);
539 fprintf(
gTraceFile,
"\n SIMD registers redundancy: %.2f\n", (*listItReg).simdRegRed);
541 fprintf(
gTraceFile,
"\n----------------------------");
547 fprintf(
gTraceFile,
"\n TODO .. Multi-threading is not well supported.");
548 THREADID threadid = PIN_ThreadId();
549 fprintf(
gTraceFile,
"\nUnloading %s", IMG_Name(img).c_str());
558 static VOID
ThreadFiniFunc(THREADID threadId,
const CONTEXT* ctxt, INT32 code, VOID* v) {
575 #ifdef MULTI_THREADED
583 int main(
int argc,
char* argv[]) {
585 if (PIN_Init(argc, argv))
605 PIN_AddFiniFunction(
FiniFunc,
nullptr);
607 IMG_AddInstrumentFunction(
Overrides,
nullptr);
#define INTERESTING_INS_MEMORY_ACCESS
DataHandle_t GetDataObjectHandle(VOID *address, const THREADID threadId)
int PinCCTLibInit(IsInterestingInsFptr isInterestingIns, FILE *logFile, CCTLibInstrumentInsCallback userCallback, VOID *userCallbackArg, BOOL doDataCentric=false)
hpcrun_metricFlags_t flags
VOID PrintFullCallingContext(const ContextHandle_t ctxtHandle)
struct DataHandle_t { uint8_t objectType DataHandle_t
ContextHandle_t GetContextHandle(const THREADID id, const uint32_t slot)
static void ClientInit(int argc, char *argv[])
int main(int argc, char *argv[])
static VOID ImageUnload(IMG img, VOID *v)
static RedSpyThreadData * gSingleThreadedTData
static unordered_map< uint32_t, list< IntraRegsRed > > regsRed[THREAD_MAX]
static void PrintRedundancyPairs(THREADID threadId)
VOID RecordIntraArrayRedundancy(const string &name, const IntraRedRecord &redPair, THREADID threadId)
#define SAME_RECORD_LIMIT
static bool RedundacyCompare(const struct RedundacyData &first, const struct RedundacyData &second)
VOID RecordIntraRegsRedundancy(uint32_t ctxt, IntraRegsRed redPair, THREADID threadId)
static string ConvertListToString(list< uint32_t > inlist)
struct intraRegsRed { double genRegRed IntraRegsRed
struct valueGroup { list< uint32_t > indexes ValueGroup
#define REG_ANALYSIS_FN_NAME
struct intraRedRecord { double redundancy IntraRedRecord
static VOID ThreadFiniFunc(THREADID threadId, const CONTEXT *ctxt, INT32 code, VOID *v)
static VOID InstrumentInsCallback(INS ins, VOID *v, const uint32_t opaqueHandle)
static void CheckRegValues(CONTEXT *ctxt, THREADID threadId)
static void InitThreadData(RedSpyThreadData *tdata)
#define ARRAY_ANALYSIS_FN_NAME
RedSpyThreadData * ClientGetTLS(const THREADID threadId)
static unordered_map< string, list< IntraRedRecord > > arrayDataRed[THREAD_MAX]
static VOID FiniFunc(INT32 code, VOID *v)
void new_ARRAY_ANALYSIS_FN_NAME(const char *name, void *addr, uint32_t typeSize, uint32_t stride, bool isApprox, THREADID threadId)
VOID Overrides(IMG img, VOID *v)
static TLS_KEY client_tls_key
static VOID ThreadStart(THREADID threadid, CONTEXT *ctxt, INT32 flags, VOID *v)
list< uint32_t > spatialRedInd
uint8_t value[MAX_WRITE_OP_LENGTH]
list< ValueGroup > maxList
typename unordered_map< T, list< uint32_t > >::iterator MyIterator
list< uint32_t > spatialRedIndex
static __attribute__((always_inline)) bool CheckIntraArrayRedundancy(uint64_t begAddr