fix negated set pnc with float compare problem
[libfirm] / ir / be / tools / instrument.cpp
1 /**
2  * Simple naive instrumentation on (x86) assembler files
3  * @author Matthias Braun (warning this is a 30 minutes hack and no nice code!)
4  *
5  * Takes an assembler file and adds instrumentation code to some instructions.
6  * You have to link the output with saveinstr.c
7  *
8  * Example usage with a file queens.s:
9  *
10  *    (adapt is_instr function here to your needs and compile instrument.cpp)
11  *    instrument < queens.s > queensi.s
12  *    gcc queensi.s saveinstr.c -o queensi
13  *    ./queensi         (run with you desired arguments and testdata)
14  *    instrument -a < queens.s > queens_annotated.s
15  *    You will get a list of the hottest spots in your file and an assembler
16  *    will the instructions prefixed with their execution count
17  */
18 #include <stdio.h>
19 #include <assert.h>
20 #include <ctype.h>
21 #include <string.h>
22 #include <vector>
23 #include <string>
24 #include <algorithm>
25
26 /** checks if we have an instruction that should be instrumented */
27 bool is_instr(const char* str)
28 {
29     if(str[0] != '\t')
30         return false;
31     if(str[1] == '.')
32         return false;
33     if(isspace(str[1]))
34         return false;
35     if(str[1] == 'c' && str[2] == 'a' && str[3] == 'l')
36         return true;
37     if(str[1] == 'j')
38         return true;
39     if(str[1] == 'p')
40         return true;
41
42     return false;
43 }
44
45 struct place {
46     int line;
47     unsigned int count;
48
49         bool operator <(const place& other) const
50         {
51                 return count > other.count;
52         }
53 };
54
55 int main(int argc, char** argv)
56 {
57     char linebuf[2048];
58     int instrcount = 0;
59         bool annotate = false;
60     std::vector<place> places;
61         int line = 0;
62
63     FILE* file = stdin;
64         FILE* instr = NULL;
65
66         // annotation mode?
67         if(argc == 2 && std::string(argv[1]) == "-a") {
68                 annotate = true;
69                 instr = fopen("instr.out", "r");
70                 assert(instr != NULL);
71         }
72
73     while(!feof(file)) {
74         fgets(linebuf, sizeof(linebuf), file);
75                 line++;
76         if(feof(file))
77             break;
78
79         if(is_instr(linebuf)) {
80                         if(annotate) {
81                                 place p;
82                                 p.line = line;
83                                 assert(fread(&p.count, 4, 1, instr) == 1);
84                                 printf("/* %u */ ", p.count);
85
86                                 places.push_back(p);
87                         } else {
88                                 printf("\tpushf\n");
89                                 printf("\tinc DWORD PTR[__instr + %d]\n", (instrcount++) * 4);
90                                 printf("\tpopf\n");
91                         }
92         }
93
94         printf("%s", linebuf);
95
96                 if(!annotate) {
97                         if(strcmp(linebuf, "main:\n") == 0) {
98                                 printf("\tsub %%esp, 4\n"
99                                                 "\tmov DWORD PTR[%%esp], OFFSET FLAT:__saveinstr\n"
100                                                 "\tcall atexit\n"
101                                                 "\tadd %%esp, 4\n");
102                         }
103                 }
104     }
105
106         if(!annotate) {
107                 printf("\n\t.section .bss\n"
108                                 ".global __instr\n"
109                                 "__instr:\n"
110                                 "\t.space %d\n"
111                                 ".global __instrend\n"
112                                 "__instrend:\n", instrcount * 4);
113         } else {
114                 std::sort(places.begin(), places.end());
115
116                 for(int i = 0; i < 20 && i < places.size(); ++i) {
117                         const place &p = places[i];
118                         fprintf(stderr, "line %d: %u\n", p.line, p.count);
119                 }
120         }
121
122     fclose(file);
123 }