CCTLib
Calling-context and data-object attribution library for Intel Pin
redspy_spatial_userdefine_client.cpp
Go to the documentation of this file.
1 // @COPYRIGHT@
2 // Licensed under MIT license.
3 // See LICENSE.TXT file in the project root for more information.
4 // ==============================================================
5 
6 #include <inttypes.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <stdint.h>
10 #include <iostream>
11 #include <unistd.h>
12 #include <assert.h>
13 #include <string.h>
14 #include <list>
15 #include <sys/mman.h>
16 #include <sstream>
17 #include <functional>
18 #include <unordered_set>
19 #include <vector>
20 #include <unordered_map>
21 #include <algorithm>
22 #include "pin.H"
23 #include "pin_isa_compat.H"
24 
25 //enable Data-centric
26 #define USE_TREE_BASED_FOR_DATA_CENTRIC
27 #define USE_TREE_WITH_ADDR
28 #include "cctlib.H"
29 using namespace std;
30 using namespace PinCCTLib;
31 
32 #define THREAD_MAX (1024)
33 
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)
40 
41 #define SAME_RATE (0.1)
42 #define SAME_RECORD_LIMIT (0)
43 #define RED_RATE (0.9)
44 #define APPROX_RATE (0.01)
45 
46 #define ARRAY_UPDATE_THRESHOLD(a) (a / 4)
47 #define MAKE_CONTEXT_PAIR(a, b) (((uint64_t)(a) << 32) | ((uint64_t)(b)))
48 
49 #define ARRAY_ANALYSIS_FN_NAME "Analyze_this_array"
50 #define REG_ANALYSIS_FN_NAME "Analyze_regs"
51 
52 
53 using ValueGroup = struct valueGroup {
54  list<uint32_t> indexes;
55 };
56 
57 using IntraRedRecord = struct intraRedRecord {
58  double redundancy;
59  uint32_t curCtxt;
60  list<ValueGroup> group;
61  list<uint32_t> spatialRedInd;
62 };
63 
64 using IntraRegsRed = struct intraRegsRed {
65  double genRegRed;
66  double x87RegRed;
67  double simdRegRed;
68 };
69 
70 struct RedSpyThreadData {
71  long long numIns;
72 };
73 
74 //helper struct used to
75 
76 // key for accessing TLS storage in the threads. initialized once in main()
77 static TLS_KEY client_tls_key;
79 
80 // function to access thread-specific data
81 inline RedSpyThreadData* ClientGetTLS(const THREADID threadId) {
82 #ifdef MULTI_THREADED
83  RedSpyThreadData* tdata =
84  static_cast<RedSpyThreadData*>(PIN_GetThreadData(client_tls_key, threadId));
85  return tdata;
86 #else
87  return gSingleThreadedTData;
88 #endif
89 }
90 
91 
92 static INT32 Usage() {
93  PIN_ERROR("Pin tool to gather calling context on each load and store.\n" + KNOB_BASE::StringKnobSummary() + "\n");
94  return -1;
95 }
96 
97 // Main for RedSpy, initialize the tool, register instrumentation functions and call the target program.
98 static FILE* gTraceFile;
99 uint32_t lastStatic;
100 // Initialized the needed data structures before launching the target program
101 static void ClientInit(int argc, char* argv[]) {
102  // Create output file
103  char name[MAX_FILE_PATH] = "redspy_spatial_selected.out.";
104  char* envPath = getenv("CCTLIB_CLIENT_OUTPUT_FILE");
105 
106  if (envPath) {
107  // assumes max of MAX_FILE_PATH
108  snprintf(name, sizeof(name), "%s", envPath);
109  }
110 
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";
115  gTraceFile = fopen(name, "w");
116  // print the arguments passed
117  fprintf(gTraceFile, "\n");
118 
119  for (int i = 0; i < argc; i++) {
120  fprintf(gTraceFile, "%s ", argv[i]);
121  }
122 
123  fprintf(gTraceFile, "\n");
124 }
125 
126 static unordered_map<string, list<IntraRedRecord>> arrayDataRed[THREAD_MAX];
127 static unordered_map<uint32_t, list<IntraRegsRed>> regsRed[THREAD_MAX];
128 
129 
130 VOID inline RecordIntraRegsRedundancy(uint32_t ctxt, IntraRegsRed redPair, THREADID threadId) {
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));
137  } else {
138  it->second.push_back(redPair);
139  }
140 }
141 
142 VOID inline RecordIntraArrayRedundancy(const string& name, const IntraRedRecord& redPair, THREADID threadId) {
143  unordered_map<string, list<IntraRedRecord>>::iterator it;
144  it = arrayDataRed[threadId].find(name);
145  if (it == arrayDataRed[threadId].end()) {
146  list<IntraRedRecord> newlist;
147  newlist.push_back(redPair);
148  arrayDataRed[threadId].insert(std::pair<string, list<IntraRedRecord>>(name, newlist));
149  } else {
150  it->second.push_back(redPair);
151  }
152 }
153 
154 static void CheckRegValues(CONTEXT* ctxt, THREADID threadId) {
155  //ContextHandle_t curCtxtHandle = GetContextHandle(threadId, 0);
156 
157  //get values for general registers
158  UINT8** genRegs;
159  genRegs = (UINT8**)malloc(GEN_REG_NUM * sizeof(UINT8*));
160  for (int i = 0; i < GEN_REG_NUM; ++i) {
161  genRegs[i] = (UINT8*)malloc(GEN_REG_LEN * sizeof(UINT8));
162  }
163 
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]);
168 
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]);
173 
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]);
182 
183  //get values for X87 registers
184  UINT8** x87Regs;
185  x87Regs = (UINT8**)malloc(X87_REG_NUM * sizeof(UINT8*));
186  for (int i = 0; i < X87_REG_NUM; ++i) {
187  x87Regs[i] = (UINT8*)malloc(X87_REG_LEN * sizeof(UINT8));
188  }
189 
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]);
198 
199  //get values for SIMD registers
200  UINT8** simdRegs;
201  simdRegs = (UINT8**)malloc(SIMD_REG_NUM * sizeof(UINT8*));
202  for (int i = 0; i < SIMD_REG_NUM; ++i) {
203  simdRegs[i] = (UINT8*)malloc(SIMD_REG_LEN * sizeof(UINT8));
204  }
205 
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]);
222 
223  int index = 0;
224  int i, j;
225 
226  //check redundancy in general registers
227  uint64_t valuesMap[GEN_REG_NUM];
228  valuesMap[index++] = *(uint64_t*)(genRegs[0]);
229 
230  for (int i = 1; i < GEN_REG_NUM; ++i) {
231  for (j = 0; j < index; ++j) {
232  if (*(uint64_t*)(genRegs[i]) == valuesMap[j]) {
233  break;
234  }
235  }
236  if (j >= index) {
237  valuesMap[index++] = *(uint64_t*)(genRegs[i]);
238  }
239  }
240 
241  float genRegRate = (float)index / GEN_REG_NUM;
242 
243  //check redundancy in x87 registers
244  UINT8** x87values;
245  x87values = (UINT8**)malloc(X87_REG_NUM * sizeof(UINT8*));
246  for (int i = 0; i < X87_REG_NUM; ++i) {
247  x87values[i] = (UINT8*)malloc(X87_REG_LEN * sizeof(UINT8));
248  }
249  index = 0;
250  memcpy(x87values[index++], x87Regs[0], X87_REG_LEN * sizeof(UINT8));
251  for (int i = 1; i < X87_REG_NUM; ++i) {
252  for (j = 0; j < index; ++j) {
253  if (memcmp(x87values[j], x87Regs[i], X87_REG_LEN * sizeof(UINT8)) == 0) {
254  break;
255  }
256  }
257  if (j >= index) {
258  memcpy(x87values[index++], x87Regs[i], X87_REG_LEN * sizeof(UINT8));
259  }
260  }
261  float x87RegRate = (float)index / X87_REG_NUM;
262 
263  //check redundancy in SIMD registers
264  UINT8** simdValues;
265  simdValues = (UINT8**)malloc(SIMD_REG_NUM * sizeof(UINT8*));
266  for (int i = 0; i < SIMD_REG_NUM; ++i) {
267  simdValues[i] = (UINT8*)malloc(SIMD_REG_LEN * sizeof(UINT8));
268  }
269  index = 0;
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) {
274  break;
275  }
276  }
277  if (j >= index) {
278  memcpy(simdValues[index++], simdRegs[i], SIMD_REG_LEN * sizeof(UINT8));
279  }
280  }
281  float simdRegRate = (float)index / SIMD_REG_NUM;
282 
283  if (genRegRate > RED_RATE || x87RegRate > RED_RATE || simdRegRate > RED_RATE) {
284  ContextHandle_t curCtxtHandle = GetContextHandle(threadId, 0);
285  IntraRegsRed newpair;
286  newpair.genRegRed = genRegRate;
287  newpair.x87RegRed = x87RegRate;
288  newpair.simdRegRed = simdRegRate;
289  RecordIntraRegsRedundancy(curCtxtHandle, newpair, threadId);
290  }
291 }
292 
293 
294 template <typename T, bool isApprox>
296  using MyIterator = typename unordered_map<T, list<uint32_t>>::iterator;
297 
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;
301  list<uint32_t> spatialRedIndex;
302  uint64_t address = begAddr;
303  uint32_t index = 0;
304  T valueLast = 0;
305  while (address < endAddr) {
306  T value = *static_cast<T*>((void*)address);
307 
308  if (isApprox) {
309  T r = (value - valueLast) / value;
310  if (r < APPROX_RATE && r > -APPROX_RATE)
311  spatialRedIndex.push_back(index);
312  for (mapIt = valuesMap.begin(); mapIt != valuesMap.end(); ++mapIt) {
313  r = (value - mapIt->first) / value;
314  if (r < APPROX_RATE && r > -APPROX_RATE) {
315  mapIt->second.push_back(index);
316  break;
317  }
318  }
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));
323  }
324  } else {
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));
332  } else {
333  mapIt->second.push_back(index);
334  }
335  }
336  address += stride;
337  index++;
338  valueLast = value;
339  }
340  uint32_t numUniqueValue = valuesMap.size();
341  double redRate = (double)(index - numUniqueValue) / index;
342  list<ValueGroup> maxList;
343  for (mapIt = valuesMap.begin(); mapIt != valuesMap.end(); ++mapIt) {
344  if (mapIt->second.size() > index * SAME_RATE) {
345  ValueGroup newGroup;
346  newGroup.indexes = mapIt->second;
347  maxList.push_back(newGroup);
348  }
349  }
350  if (redRate > RED_RATE || maxList.size() > SAME_RECORD_LIMIT) {
351  newPair->redundancy = redRate;
352  newPair->group = maxList;
353  newPair->spatialRedInd = spatialRedIndex;
354  return true;
355  }
356  return false;
357  }
358 };
359 
360 static VOID InstrumentInsCallback(INS ins, VOID* v, const uint32_t opaqueHandle) {
361  ;
362 }
363 
364 void new_ARRAY_ANALYSIS_FN_NAME(const char* name, void* addr, uint32_t typeSize, uint32_t stride, bool isApprox, THREADID threadId) {
365  //printf("name:%s, addr:%p, type:%d, stride:%d\n",name,addr,typeSize,stride);
366  string str(name);
367 
368  DataHandle_t dataHandle = GetDataObjectHandle(addr, threadId);
369  IntraRedRecord newRecord;
370  bool hasRedundant = false;
371 
372  if (isApprox) {
373  switch (typeSize) {
374  case 4:
375  hasRedundant = ArrayAnalysis<float, true>::CheckIntraArrayRedundancy(dataHandle.beg_addr, dataHandle.end_addr, stride, &newRecord);
376  break;
377  case 8:
378  hasRedundant = ArrayAnalysis<double, true>::CheckIntraArrayRedundancy(dataHandle.beg_addr, dataHandle.end_addr, stride, &newRecord);
379  break;
380  default:
381  assert(0 && "approx inappropriate type size, should not reach here!");
382  break;
383  }
384  } else {
385  switch (typeSize) {
386  case 1:
387  hasRedundant = ArrayAnalysis<uint8_t, false>::CheckIntraArrayRedundancy(dataHandle.beg_addr, dataHandle.end_addr, stride, &newRecord);
388  break;
389  case 2:
390  hasRedundant = ArrayAnalysis<uint16_t, false>::CheckIntraArrayRedundancy(dataHandle.beg_addr, dataHandle.end_addr, stride, &newRecord);
391  break;
392  case 4:
393  hasRedundant = ArrayAnalysis<uint32_t, false>::CheckIntraArrayRedundancy(dataHandle.beg_addr, dataHandle.end_addr, stride, &newRecord);
394  break;
395  case 8:
396  hasRedundant = ArrayAnalysis<uint64_t, false>::CheckIntraArrayRedundancy(dataHandle.beg_addr, dataHandle.end_addr, stride, &newRecord);
397  break;
398  default:
399  assert(0 && "unknow element size, should not reach here!");
400  break;
401  }
402  }
403  if (hasRedundant) {
404  ContextHandle_t curCtxtHandle = GetContextHandle(threadId, 0);
405  newRecord.curCtxt = curCtxtHandle;
406  RecordIntraArrayRedundancy(name, newRecord, threadId);
407  }
408 }
409 /*
410 VOID Overrides (IMG img, VOID * v) {
411  // Master setup
412  RTN rtn = RTN_FindByName (img, ARRAY_ANALYSIS_FN_NAME);
413  if (RTN_Valid (rtn)) {
414 
415  RTN_InsertCall (rtn, IPOINT_BEFORE, (AFUNPTR) CheckRegValues, IARG_CONTEXT, IARG_THREAD_ID,IARG_END);
416  // Define a function prototype that describes the application routine
417  // that will be replaced.
418  //
419  PROTO proto_master = PROTO_Allocate (PIN_PARG (void), CALLINGSTD_DEFAULT,
420  ARRAY_ANALYSIS_FN_NAME,PIN_PARG (char *),PIN_PARG (void *),PIN_PARG (uint32_t),PIN_PARG (uint32_t), PIN_PARG (bool),
421  PIN_PARG_END ());
422 
423  // Replace the application routine with the replacement function.
424  // Additional arguments have been added to the replacement routine.
425  //
426  RTN_ReplaceSignature (rtn, AFUNPTR (new_ARRAY_ANALYSIS_FN_NAME),
427  IARG_PROTOTYPE, proto_master,
428  IARG_FUNCARG_ENTRYPOINT_VALUE, 0,
429  IARG_FUNCARG_ENTRYPOINT_VALUE, 1,
430  IARG_FUNCARG_ENTRYPOINT_VALUE, 2,
431  IARG_FUNCARG_ENTRYPOINT_VALUE, 3,
432  IARG_FUNCARG_ENTRYPOINT_VALUE, 4,
433  IARG_THREAD_ID, IARG_END);
434  // Free the function prototype.
435  PROTO_Free (proto_master);
436  }
437 }*/
438 
439 VOID Overrides(IMG img, VOID* v) {
440  // Master setup
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);
444  if (rtnName.find(ARRAY_ANALYSIS_FN_NAME) != std::string::npos) {
445  // Define a function prototype that describes the application routine
446  // that will be replaced.
447  //
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),
450  PIN_PARG_END());
451 
452  // Replace the application routine with the replacement function.
453  // Additional arguments have been added to the replacement routine.
454  //
455  RTN_ReplaceSignature(rtn, AFUNPTR(new_ARRAY_ANALYSIS_FN_NAME),
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);
463  // Free the function prototype.
464  PROTO_Free(proto_master);
465  } else if (rtnName.find(REG_ANALYSIS_FN_NAME) != std::string::npos) {
466  RTN_Open(rtn);
467  RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)CheckRegValues, IARG_CONTEXT, IARG_THREAD_ID, IARG_END);
468  RTN_Close(rtn);
469  }
470  }
471  }
472 }
473 
474 
475 struct RedundacyData {
476  ContextHandle_t dead;
477  ContextHandle_t kill;
478  uint64_t frequency;
479 };
480 
481 static inline string ConvertListToString(list<uint32_t> inlist) {
482  list<uint32_t>::iterator it = inlist.begin();
483  uint32_t tmp = (*it);
484  string indexList = "[" + to_string(tmp) + ",";
485  it++;
486  while (it != inlist.end()) {
487  if (*it == tmp + 1) {
488  tmp = *it;
489  } else {
490  indexList += to_string(tmp) + "],[" + to_string(*it) + ",";
491  tmp = *it;
492  }
493  it++;
494  }
495  indexList += to_string(tmp) + "]";
496  return indexList;
497 }
498 
499 
500 static inline bool RedundacyCompare(const struct RedundacyData& first, const struct RedundacyData& second) {
501  return first.frequency > second.frequency;
502 }
503 
504 static void PrintRedundancyPairs(THREADID threadId) {
505  fprintf(gTraceFile, "\n*************** Intra Array Redundancy of Thread %d ***************\n", threadId);
506  unordered_map<string, list<IntraRedRecord>>::iterator itIntra;
507 
508  fprintf(gTraceFile, "========== Selected Dataobjecy Redundancy ==========\n");
509  for (itIntra = arrayDataRed[threadId].begin(); itIntra != arrayDataRed[threadId].end(); ++itIntra) {
510  fprintf(gTraceFile, "\nVariable %s: \n", (itIntra->first).c_str());
511 
512  list<IntraRedRecord>::iterator listIt;
513  for (listIt = itIntra->second.begin(); listIt != itIntra->second.end(); ++listIt) {
514  PrintFullCallingContext((*listIt).curCtxt);
515  fprintf(gTraceFile, "\nRed:%.2f, unique value large index group:\n", (*listIt).redundancy);
516  list<ValueGroup>::iterator groupIt;
517  int num = 0;
518  for (groupIt = (*listIt).group.begin(); groupIt != (*listIt).group.end(); ++groupIt) {
519  string indexlist = ConvertListToString((*groupIt).indexes);
520  fprintf(gTraceFile, "Group %d: %s\n", num, indexlist.c_str());
521  }
522  string indexlist = ConvertListToString((*listIt).spatialRedInd);
523  fprintf(gTraceFile, "redundant spatial indexes:%s\n", indexlist.c_str());
524  }
525  fprintf(gTraceFile, "\n----------------------------");
526  }
527 
528  fprintf(gTraceFile, "\n*************** Intra Registers Redundancy of Thread %d ***************\n", threadId);
529  unordered_map<uint32_t, list<IntraRegsRed>>::iterator itIntraReg;
530 
531  fprintf(gTraceFile, "========== ==========\n");
532  for (itIntraReg = regsRed[threadId].begin(); itIntraReg != regsRed[threadId].end(); ++itIntraReg) {
533  PrintFullCallingContext(itIntraReg->first);
534 
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);
540  }
541  fprintf(gTraceFile, "\n----------------------------");
542  }
543 }
544 
545 // On each Unload of a loaded image, the accummulated redundancy information is dumped
546 static VOID ImageUnload(IMG img, VOID* v) {
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());
550  // Update gTotalInstCount first
551  PIN_LockClient();
552  PrintRedundancyPairs(threadid);
553  PIN_UnlockClient();
554  // clear redmap now
555  arrayDataRed[threadid].clear();
556 }
557 
558 static VOID ThreadFiniFunc(THREADID threadId, const CONTEXT* ctxt, INT32 code, VOID* v) {
559 }
560 
561 static VOID FiniFunc(INT32 code, VOID* v) {
562  // do whatever you want to the full CCT with footpirnt
563 }
564 
565 
566 static void InitThreadData(RedSpyThreadData* tdata) {
567  tdata->numIns = 0;
568 }
569 
570 static VOID ThreadStart(THREADID threadid, CONTEXT* ctxt, INT32 flags, VOID* v) {
571  RedSpyThreadData* tdata = new RedSpyThreadData();
572  InitThreadData(tdata);
573  // __sync_fetch_and_add(&gClientNumThreads, 1);
574  PIN_SetThreadData(client_tls_key, tdata, threadid);
575 #ifdef MULTI_THREADED
576  PIN_SetThreadData(client_tls_key, tdata, threadid);
577 #else
578  gSingleThreadedTData = tdata;
579 #endif
580 }
581 
582 
583 int main(int argc, char* argv[]) {
584  // Initialize PIN
585  if (PIN_Init(argc, argv))
586  return Usage();
587 
588  // Initialize Symbols, we need them to report functions and lines
589  PIN_InitSymbols();
590 
591  // Init Client
592  ClientInit(argc, argv);
593  // Intialize CCTLib
595 
596 
597  // Obtain a key for TLS storage.
598  client_tls_key = PIN_CreateThreadDataKey(nullptr /*TODO have a destructir*/);
599  // Register ThreadStart to be called when a thread starts.
600  PIN_AddThreadStartFunction(ThreadStart, nullptr);
601 
602 
603  // fini function for post-mortem analysis
604  PIN_AddThreadFiniFunction(ThreadFiniFunc, nullptr);
605  PIN_AddFiniFunction(FiniFunc, nullptr);
606 
607  IMG_AddInstrumentFunction(Overrides, nullptr);
608 
609  // Register ImageUnload to be called when an image is unloaded
610  IMG_AddUnloadFunction(ImageUnload, nullptr);
611 
612  // Launch program now
613  PIN_StartProgram();
614  return 0;
615 }
#define MAX_FILE_PATH
Definition: cctlib.H:18
#define INTERESTING_INS_MEMORY_ACCESS
Definition: cctlib.H:87
DataHandle_t GetDataObjectHandle(VOID *address, const THREADID threadId)
Definition: cctlib.cpp:2495
int PinCCTLibInit(IsInterestingInsFptr isInterestingIns, FILE *logFile, CCTLibInstrumentInsCallback userCallback, VOID *userCallbackArg, BOOL doDataCentric=false)
Definition: cctlib.cpp:3132
hpcrun_metricFlags_t flags
Definition: cctlib.cpp:3425
VOID PrintFullCallingContext(const ContextHandle_t ctxtHandle)
Definition: cctlib.cpp:2346
struct DataHandle_t { uint8_t objectType DataHandle_t
Definition: cctlib.H:32
ContextHandle_t GetContextHandle(const THREADID id, const uint32_t slot)
Definition: cctlib.cpp:1356
uint32_t ContextHandle_t
Definition: cctlib.H:22
static void ClientInit(int argc, char *argv[])
int main(int argc, char *argv[])
static FILE * gTraceFile
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)
static bool RedundacyCompare(const struct RedundacyData &first, const struct RedundacyData &second)
VOID RecordIntraRegsRedundancy(uint32_t ctxt, IntraRegsRed redPair, THREADID threadId)
static INT32 Usage()
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
list< ValueGroup > group
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]
void * address
typename unordered_map< T, list< uint32_t > >::iterator MyIterator
static __attribute__((always_inline)) bool CheckIntraArrayRedundancy(uint64_t begAddr