[project @ 1996-07-19 18:36:04 by partain]
[ghc-hetmet.git] / ghc / misc / spat-analysers / icount_by_activity.c
1 #define VERSION         "24-Jan-95"
2 #define PROGNAME        "ICountByActivity"
3
4 #define SHADE
5
6 #include <stdio.h>
7
8 #include <IHASH.h>
9 #include <ITYPES.h>
10 #include <instr.h>
11 #include <inames.h>
12
13 #include <shade.h>
14 #define TR_REGS
15 #include <trace.h>
16 #include <stdtr.h>
17 #include <trctl.h>
18
19 int shade_run(Trace *, int);
20
21 #define DO_SPAT_PROFILING
22 #define __STG_USING_ULLONG__
23 #include "stgdefs.h"    /* GHC ticky-counting stuff */
24 #define ACTIVITY_REG I_REG_g5
25 #define SpA_REG      I_REG_i0
26 #define SpB_REG      I_REG_i2
27 #define Hp_REG       I_REG_i4
28 #define RET_REG      I_REG_l0
29 #define NODE_REG     I_REG_l1
30 #define INFO_REG     I_REG_l2
31 #define R3_REG       I_REG_l3
32 #define R7_REG       I_REG_l7
33
34 /* Activity register and current activity */
35
36 #define EACT_CALL       (ACTIVITIES+0)
37 #define EACT_STKADJ     (ACTIVITIES+1)
38 #define EACT_ASTK       (ACTIVITIES+2)
39 #define EACT_BSTK       (ACTIVITIES+3)
40 #define EACT_RETREG     (ACTIVITIES+4)
41 #define EACT_ARGREGS    (ACTIVITIES+5)
42
43 #define EACT_TAILCALL   (ACT_TAILCALL - ACT_BASE) /* use the TAILCALL slot */
44 #define EACT_OVERHEAD   (ACT_OVERHEAD - ACT_BASE) /* only used herein */
45
46 #define EXTRA_ACTIVITIES 6
47
48 #define TOTAL_ACTIVITIES (ACTIVITIES+EXTRA_ACTIVITIES)
49
50 static ullong info[TOTAL_ACTIVITIES][NIHASH];
51 /*static ullong annulled_insns = 0;*/
52
53 #define STATS_FILE      "ICNT_BY_ACTIVITY"
54
55 /* fwd decls */
56 void print_results(char *);
57 void fprintf_ullong(FILE *, ullong);
58
59 #define CHECKPOINT (1024*1024)  /* reporting frequency */
60 static long countdown = CHECKPOINT;
61
62 char    *anal_usage = "";
63 char    *anal_version = VERSION;
64
65 void
66 initialize(argc,argv,envp)
67   int    argc;
68   char **argv, envp;
69 {
70     unsigned i, j;
71
72     /* Setup the trace */
73     shade_trctl_trsize(sizeof(Trace));
74
75     shade_trctl_it (IT_ANY,   1, 0, TC_I | TC_IH);
76     shade_trctl_ih (IH_OR,    1, 0, TC_I | TC_IH | TC_RD);
77     shade_trctl_ih (IH_ADD,   1, 0, TC_I | TC_IH | TC_RD | TC_RS1);
78     shade_trctl_ih (IH_SETHI, 1, 0, TC_I | TC_IH | TC_RD);
79     shade_trctl_it (IT_LOAD,  1, 0, TC_I | TC_IH | TC_RD | TC_RS1);
80     shade_trctl_it (IT_ILOAD, 1, 0, TC_I | TC_IH | TC_RD | TC_RS1);
81     shade_trctl_it (IT_STORE, 1, 0, TC_I | TC_IH | TC_RD | TC_RS1);
82     shade_trctl_it (IT_ISTORE,1, 0, TC_I | TC_IH | TC_RD | TC_RS1);
83         /* trace all non-annulled instructions (... 1, 0, ...); For
84            them, we want the instruction text (TC_I), and the hashed
85            opcode (TC_IH).  For "or" instructions, we also want the
86            contents the destination register that was written into
87            (TC_RD).  Etc.
88         */
89
90     /* init table */
91     for (i = 0; i < TOTAL_ACTIVITIES; i++)
92         for (j = 0; j < NIHASH; j++)
93             info[i][j] = 0LL;
94 }
95
96 int analyze(argc,argv,envp)
97   int    argc;
98   char **argv, envp;
99 {
100     Trace *tr;
101     ullong i;
102     uint16 ih;
103     int32  rd, rs1;
104
105     unsigned activity = (ACT_UNKNOWN - ACT_BASE);
106     ullong pending_sethi = 0LL;
107     ullong pending_or    = 0LL;
108     ullong activity_chgs = 0LL;
109     int acctd_for;
110 #define ACCT_FOR() acctd_for = 1
111
112     for (i = 0LL; tr = shade_step(); i += 1LL) {
113         acctd_for = 0;
114         ih = tr->tr_ih;
115
116         if ( ih == IH_OR && tr->tr_i.i_rd == ACTIVITY_REG) {
117             rd = tr->tr_rd;
118
119             info[EACT_TAILCALL][IH_OR] += pending_or;
120             if ( pending_sethi ) {
121                 fprintf(stderr, "pending_sethi still set!\n");
122             }
123
124             if (activity == (ACT_GC - ACT_BASE)) { /* only GC_STOP will stop it */
125                 if (rd == ACT_GC_STOP) {
126                     activity = ACT_UNKNOWN - ACT_BASE;
127                     info[EACT_OVERHEAD][IH_OR] += 1LL;
128                     ACCT_FOR();
129                 } else {
130                     info[activity][IH_OR] += 1LL;
131                     ACCT_FOR();
132                 }
133             } else {
134                 if (rd < ACT_BASE || rd >= (ACT_BASE+ACTIVITIES)) {
135                     info[activity][IH_OR] += 1LL;
136                     ACCT_FOR();
137                 } else {
138                     activity = rd - ACT_BASE; /* reset! */
139                     info[EACT_OVERHEAD][IH_OR] += 1LL;
140                     ACCT_FOR();
141                 }
142             }
143             activity_chgs += 1LL;
144             pending_sethi  = 0LL;
145             pending_or     = 0LL;
146             /* reset other things? */
147
148         } else if ( activity != EACT_TAILCALL ) { /* ordinary instruction */
149             info[activity][ih] += 1LL;
150             ACCT_FOR();
151
152         } else { /* TAILCALLing */
153 /*          fprintf(stderr, "op=%d\n", ih); */
154
155             switch (ih) {
156               case IH_SETHI:
157 /*                      if ( pending_sethi ) {
158                             fprintf(stderr, "pending_sethi already set!\n");
159                         }
160 */                      pending_sethi += 1LL;
161                         ACCT_FOR();
162                         break;
163               case IH_JMPL:
164               case IH_CALL:
165               case IH_NOP:
166                         info[EACT_CALL][ih]       += 1LL;
167                         info[EACT_CALL][IH_SETHI] += pending_sethi; /* really mystery? */
168                         info[EACT_CALL][IH_OR]    += pending_or;    /* ditto? */
169                         pending_sethi = 0LL;
170                         pending_or    = 0LL;
171                         ACCT_FOR();
172                         break;
173             
174               case IH_ADD:
175               case IH_ADDCC:
176               case IH_SUB:
177               case IH_SUBCC:
178                         rd  = tr->tr_i.i_rd;
179                         rs1 = tr->tr_i.i_rs1;
180                         if ( rd == NODE_REG || rd == INFO_REG ) {
181                             info[EACT_CALL][ih]       += 1LL;
182                             info[EACT_CALL][IH_SETHI] += pending_sethi;
183                             info[EACT_CALL][IH_OR]    += pending_or;
184                             pending_sethi = 0LL;
185                             pending_or    = 0LL;
186                             ACCT_FOR();
187
188                         } else if (rd >= R3_REG && rd <= R7_REG) {
189                             info[EACT_ARGREGS][ih]       += 1LL;
190                             info[EACT_ARGREGS][IH_SETHI] += pending_sethi;
191                             info[EACT_ARGREGS][IH_OR]    += pending_or;
192                             pending_sethi = 0LL;
193                             pending_or    = 0LL;
194                             ACCT_FOR();
195
196                         } else {
197                             info[EACT_TAILCALL][IH_SETHI] += pending_sethi;
198                             info[EACT_TAILCALL][IH_OR]    += pending_or;
199                             pending_sethi = 0LL;
200                             pending_or    = 0LL;
201
202                             if ( (rd == SpA_REG && rs1 == SpA_REG)
203                               || (rd == SpB_REG && rs1 == SpB_REG) ) {
204                                 info[EACT_STKADJ][ih] += 1LL;
205                                 ACCT_FOR();
206
207                             } else if ( rd >= I_REG_o0 && rd <= I_REG_o7 ) {
208                                 info[EACT_TAILCALL][ih] += 1LL;
209                                 ACCT_FOR();
210
211                             } else if ( rd == I_REG_g0
212                                     && rs1 >= I_REG_o0 && rs1 <= I_REG_o7 ) {
213                                 info[EACT_TAILCALL][ih] += 1LL;
214                                 ACCT_FOR();
215
216                             } else if ( rd == I_REG_g3 && rs1 == I_REG_g3 ) {
217                                 info[EACT_TAILCALL][ih] += 1LL;
218                                 ACCT_FOR();
219
220                             } else {
221                               fprintf(stderr, "IH_ADD: mystery op (%d) rd=%d rs1=%d\n",
222                                     ih, rd, rs1);
223                             }
224                         }
225                         break;
226
227               case IH_OR:
228               case IH_ORCC:
229                         rd  = tr->tr_i.i_rd;
230                         if ( rd == RET_REG ) {
231                             info[EACT_RETREG][ih]       += 1LL + pending_or;
232                             info[EACT_RETREG][IH_SETHI] += pending_sethi;
233                             pending_sethi = 0LL;
234                             pending_or    = 0LL;
235                             ACCT_FOR();
236
237                         } else if ( rd == NODE_REG || rd == INFO_REG ) {
238                             info[EACT_CALL][ih]       += 1LL + pending_or;
239                             info[EACT_CALL][IH_SETHI] += pending_sethi;
240                             pending_sethi = 0LL;
241                             pending_or    = 0LL;
242                             ACCT_FOR();
243
244                         } else {
245                             pending_or += 1LL;
246                             ACCT_FOR();
247                         }
248                         break;
249
250               case IH_LD:
251               case IH_LDUB: /* ??? */
252               case IH_ST:
253                         rs1 = tr->tr_i.i_rs1;
254                         if ( rs1 == SpA_REG ) {
255                             info[EACT_ASTK][ih]       += 1LL;
256                             info[EACT_ASTK][IH_SETHI] += pending_sethi;
257                             info[EACT_ASTK][IH_OR]    += pending_or;
258                             pending_sethi = 0LL;
259                             pending_or    = 0LL;
260                             ACCT_FOR();
261
262                         } else if ( rs1 == SpB_REG ) {
263                             info[EACT_BSTK][ih]       += 1LL;
264                             info[EACT_BSTK][IH_SETHI] += pending_sethi;
265                             info[EACT_BSTK][IH_OR]    += pending_or;
266                             pending_sethi = 0LL;
267                             pending_or    = 0LL;
268                             ACCT_FOR();
269
270                         } else if ( rs1 == NODE_REG ) {
271                             info[EACT_CALL][ih]       += 1LL;
272                             info[EACT_CALL][IH_SETHI] += pending_sethi;
273                             info[EACT_CALL][IH_OR]    += pending_or;
274                             pending_sethi = 0LL;
275                             pending_or    = 0LL;
276                             ACCT_FOR();
277
278                         } else { /* random ld/st */
279                             info[EACT_TAILCALL][ih]       += 1LL;
280                             info[EACT_TAILCALL][IH_SETHI] += pending_sethi;
281                             info[EACT_TAILCALL][IH_OR]    += pending_or;
282                             pending_sethi = 0LL;
283                             pending_or    = 0LL;
284                             ACCT_FOR();
285                         }
286                         break;
287
288               case IH_AND:      /* ??? */
289               case IH_BA:       /* ??? */
290               case IH_BAA:
291               case IH_BCC:
292               case IH_BCS:
293               case IH_BE:
294               case IH_BGE:
295               case IH_BL:
296               case IH_BLA:
297               case IH_BLEU:
298               case IH_BNE:
299               case IH_SLL:
300               case IH_SRL:
301               case IH_XOR:
302                         info[EACT_TAILCALL][ih]   += 1LL;
303                         info[EACT_TAILCALL][IH_SETHI] += pending_sethi;
304                         info[EACT_TAILCALL][IH_OR]    += pending_or;
305                         pending_sethi = 0LL;
306                         pending_or    = 0LL;
307                         ACCT_FOR();
308                         break;
309
310               default:
311                         fprintf(stderr, "mystery TAIL op = %d\n", ih);
312                         break;
313             }
314         }
315
316         if (countdown-- < 0) {
317           print_results("Intermediate:");
318           countdown = CHECKPOINT;
319         }
320         if ( ! acctd_for ) {
321           fprintf(stderr, "insn op=%d not acctd for!\n", ih);
322         }
323     }
324     fprintf(stderr,"\n");
325     fprintf_ullong(stderr,i);
326     fprintf(stderr," iterations; ");
327     fprintf_ullong(stderr,activity_chgs);
328     fprintf(stderr," activity changes\n");
329     return(0);
330 }
331
332 void
333 terminate()
334 {
335     print_results("Final:");
336 }
337
338 void
339 print_results(header)
340   char *header;
341 {
342     int i, j;
343     long total_slots = 0;
344     ullong total_instrs = 0;
345     static FILE *statf = NULL;
346
347 /*  fprintf(stderr, "Printing %s\n", header); */
348
349     unlink(STATS_FILE);
350     if ((statf = fopen(STATS_FILE, "w")) == NULL) {
351       fprintf(stderr, "Cannot open statistics file %s\n",STATS_FILE);
352       exit(1);
353     }
354     fprintf(statf, "%s\n\n", header);
355 /*  fprintf(statf, "annulled insns = ");
356     fprintf_ullong(statf, annulled_insns);
357 */  fprintf(statf, "\n\n");
358
359     for (i = 0; i < NIHASH; i++) {
360         fprintf(statf, "%8d:", i);
361         for (j = 0; j < TOTAL_ACTIVITIES; j++) {
362             fprintf(statf, " ");
363             fprintf_ullong(statf, info[j][i]);
364             total_slots++;
365             total_instrs += info[j][i];
366         }
367         fprintf(statf, "\n");
368     }
369     fprintf(statf, "total slots=%ld, total instructions=", total_slots);
370     fprintf_ullong(statf, total_instrs);
371     fprintf(statf, "\n");
372
373     fclose(statf);
374 }
375
376 void
377 fprintf_ullong(FILE *filep, ullong x)
378 {
379     if (x < (ullong)1000) 
380         fprintf(filep, "%ld", (I_)x);
381     else if (x < (ullong)1000000)
382         fprintf(filep, "%ld%3.3ld",
383                 (I_)((x)/(ullong)1000),
384                 (I_)((x)%(ullong)1000));
385     else if (x < (ullong)1000000000)
386         fprintf(filep, "%ld%3.3ld%3.3ld",
387                 (I_)((x)/(ullong)1000000),
388                 (I_)((x)/(ullong)1000%(ullong)1000),
389                 (I_)((x)%(ullong)1000));
390     else
391         fprintf(filep, "%ld%3.3ld%3.3ld%3.3ld",
392                 (I_)((x)/(ullong)1000000000),
393                 (I_)((x)/(ullong)1000000%(ullong)1000),
394                 (I_)((x)/(ullong)1000%(ullong)1000), 
395                 (I_)((x)%(ullong)1000));
396 }