Move the sources to trunk
[opencv] / apps / cvenv / EiC / optomizer.c
1 /* optomizer.c
2  *
3  *      (C) Copyright Jul 27 1996, Edmond J. Breen.
4  *                 ALL RIGHTS RESERVED.
5  * This code may be copied for personal, non-profit use only.
6  *
7  */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12
13 #include "MachSet.h"
14 #include "global.h"
15 #include "typesets.h"
16 #include "error.h"
17
18 #define isgoto(C,i)  (opcode(C,i) >= jmpu && opcode(C,i) <= jmpTptr)
19
20 typedef struct {
21     int ninst;        /* # of instructions */
22     int leader;       /* block leader */
23     int nb;           /* number of braches leading from block */
24     int *branch;      /* branch leaders */
25 }block_t;
26
27 #define crt_block() (block_t*)calloc(sizeof(block_t),1)
28
29 #define addbranch(x,y,z)    do{\
30                                     x = (int*)realloc(x,(y+1)*sizeof(int));\
31                                     x[y++] = z;\
32                             }while(0)
33
34 static void freeblock(block_t * b, int nb)
35 {
36     int i;
37     for(i =0;i<nb;++i)
38         if(b[i].branch)
39             free(b[i].branch);
40     free(b);
41 }
42
43 static block_t  initblock(code_t *c, int leader, int *visit)
44 {
45     int i;
46     block_t  b;
47     b.leader = leader;
48     b.branch = NULL;
49     b.nb = 0;
50     b.ninst = 0;
51
52     for(i=leader;i<nextinst(c);++i) {
53         visit[i]++;
54         b.ninst++;
55         if(opcode(c,i) == eicreturn)
56             break;
57         else if(isgoto(c,i)) {
58             /*printf("[%d:%d]\n",i,i+ivalcode(c,i));*/
59             addbranch(b.branch,b.nb,i+ivalcode(c,i));
60             if(opcode(c,i) != jmpu) {
61                 /*printf("[%d:%d]\n",i,i+1);*/
62                 addbranch(b.branch,b.nb,i+1);
63             }
64             break;
65         } else if(opcode(c,i) == jmptab) {
66             struct {int n;val_t *loc;} *p;
67             int j;
68             p = pvalcode(c,i);
69             addbranch(b.branch,b.nb,i + p->loc[0].ival); 
70             for(j =1;j<p->n;j+=2)
71                 addbranch(b.branch,b.nb,i + p->loc[j+1].ival);
72             break;
73         }
74     }
75     if(leader == nextinst(c))
76         visit[leader]++;
77     return b;
78 }
79
80
81 void  EiC_peephole(code_t *C, int *visit)
82 {
83     int  i, n,j;
84     n = nextinst(C);
85     for(i = 0; i < n; ++i)
86         if(isgoto(C,i)) {
87             j = i + ivalcode(C,i);
88             if(j >= n)
89                 continue;
90             if(opcode(C,j) == jmpu || opcode(C,i) == opcode(C,j)) {
91                 /*visit[i+ivalcode(C,i)]--;*/
92                 ivalcode(C,i) += ivalcode(C,j);
93
94             }
95         }
96 }
97
98 int EiC_analyseCode(code_t *C)
99 {
100     /* returns the index to the last visited instruction */
101     block_t *block = NULL;
102
103     int nb = 0;
104     int  i,j,rtn;
105     int *visit;
106
107     visit = calloc(sizeof(*visit),nextinst(C)+1);
108     block = realloc(block,(nb+1)*sizeof(*block));
109     block[nb++] = initblock(C,0,visit);
110
111     for(i=0;i<nb;++i) {
112         for(j=0;j<block[i].nb;++j) {
113             if(!visit[block[i].branch[j]]) {
114                 block = realloc(block,(nb+1)*sizeof(*block));
115                 block[nb++] = initblock(C,block[i].branch[j],visit);
116             } else
117                 visit[block[i].branch[j]]++;
118         }
119     }
120         
121     rtn = 0;
122     for(i=0;i<=nextinst(C);)
123         if(visit[i]) 
124             rtn = i++;
125         else if(i < nextinst(C) && instline(C,i)) {
126             EiC_warningerror("Unreachable code at line %d",instline(C,i));          
127             for(;i<nextinst(C) && !visit[i];i++)
128                 ;
129         } else
130             i++;
131
132     EiC_peephole(C,visit);
133
134 /*******
135     for(i=0;i<nextinst(C);++i)
136         if(!visit[i])
137         setopcode(C,i,empty);
138 *******/
139     
140     freeblock(block,nb);
141     free(visit);
142
143     
144     return rtn;
145 }
146
147
148 int EiC_checkPeepHole(token_t *e1,int op)
149 {
150     /*
151      * A simple arithmetic optimizer:
152      * do not add or subtract 0
153      * and do not multiply  or divide by 1
154      */
155     int v = 0;
156     if (isconst(e1->Type)) {
157         if (op == '+' || op == '-')
158             switch (EiC_gettype(e1->Type)) {
159               CASE_INT: CASE_UINT:v = e1->Val.ival == 0;
160                 break;
161               CASE_LONG: CASE_ULONG:v = e1->Val.lval == 0;
162                 break;
163               CASE_FLOAT:v = e1->Val.dval == 0;
164                 break;
165                 }
166         else if (op == '*')
167             switch (EiC_gettype(e1->Type)) {
168               CASE_INT: CASE_UINT:v = e1->Val.ival == 1;
169                 break;
170               CASE_LONG: CASE_ULONG:v = e1->Val.lval == 1;
171                 break;
172               CASE_FLOAT:v = e1->Val.dval == 1;
173                 break;
174             }
175         }
176     return v;
177 }
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204