comparison mc-switch.c @ 297:0f79c95df73a

switch index no compile error
author kono
date Sun, 06 Jun 2004 20:19:36 +0900
parents
children 4ccacae1d2e6
comparison
equal deleted inserted replaced
296:284aa4eaab0d 297:0f79c95df73a
1 /* Micro-C Switch Code generation Part */
2 /* $Id$ */
3
4 #define EXTERN extern
5 #include "mc.h"
6 #include "mc-code.h"
7 #include "mc-codegen.h"
8
9 #if CASE_CODE
10
11 extern void genswitch(int cslist,int cslabel,int dlabel);
12
13 /*
14 value label pair
15 cslist = list3(value,next,label) label==0 means skip
16 continuous cslist
17 chunks: list4(cslist,next,delta,list3(count,min,max))
18 mergeable chunks count list
19 merge: list4(continuous number of chunk,next,delta,case_count);
20 index list
21 index: list4(label,next,max,min);
22 */
23
24 #define chunk_max(chunks) caddr(cadddr(chunks))
25 #define chunk_min(chunks) cadr(cadddr(chunks))
26 #define index_max(index) caddr(index)
27 #define index_min(index) cadddr(index)
28
29 /*
30 group continous case value
31 */
32
33 static int
34 make_chunk(int cslist)
35 {
36 int delta,delta1,list,p,count;
37 // cslist is already sorted
38 delta = 0;
39 list = list4(cslist,0,1,list3(0,car(cslist) /* min */,0));
40 count=1;
41 for(p=0;cadr(cslist);cslist = cadr(cslist),count++) {
42 // compute new delta
43 delta1 = car(cadr(cslist))-car(cslist);
44 // empty case
45 if (!caddr(cslist)) count--;
46 if (delta==0) {
47 // 2nd element
48 caddr(list) = delta = delta1;
49 if (p) cadr(p)=0; // terminate previous chunk
50 } else if (delta1!=delta) {
51 // not contiguous, start new list
52 caddr(cadddr(list)) = car(cslist); // max
53 car(cadddr(list)) = count; count=0;
54 delta = 0;
55 list = list4(cadr(cslist),list,1,list3(0,0,0));
56 cadr(cadddr(list)) = car(cadr(cslist)); // min
57 // prepare terminate point for next turn
58 p=cslist;
59 }
60 }
61 if (p) cadr(p)=0; // terminate previous chunk
62 car(cadddr(list)) = count;
63 caddr(cadddr(list)) = car(cslist); // max
64 return list;
65 }
66
67 #define CASE_MERGE_RATE 70
68
69 static int gcd(int i,int j)
70 {
71 int k;
72 if (i<j) { k=i; i=j; j=k;}
73 for(;;) {
74 if ((k=i%j)==0) return j;
75 i = j; j = k;
76 }
77 }
78
79 /*
80 check two chunks are mergeable or not.
81 */
82
83 static int
84 merge_chunk_p(int *delta,int max,int min,int *count,int delta1,int count1)
85 {
86 int range = max-min;
87 int g;
88 // compute possible merge delta
89 g = gcd(*delta,delta1);
90 g = gcd(g,range);
91 range /= g;
92 *count = count1 = count1+*count;
93 *delta = g;
94 #if 1
95 if (count1*128>(range*128*CASE_MERGE_RATE/100)) {
96 printf("# min %d, max %d, count %d, delta %d, rate %g t=%d\n",
97 min,max,count1,g,
98 ((double)count1)*100.0/range,
99 count1*128>(range*128*CASE_MERGE_RATE/100)
100 );
101 }
102 #endif
103 // count/((max-min)/delta) > 0.8
104 return count1*128>(range*128*CASE_MERGE_RATE/100);
105 }
106
107
108 static int
109 merge_chunk(int chunks)
110 {
111 int list = chunks;
112 int tail,last,max,min,i;
113 int count,c_count,p,widest,delta=1;
114 int merge = 0;
115 while(cadr(list)) {
116 p = cadddr(list);
117 c_count = count = car(p); max=caddr(p);
118 widest = 1; last = list;
119 delta = caddr(list);
120 // check possible merge against the end of the chunks
121 for(i=1,tail=cadr(list);cadr(tail); tail=cadr(tail),i++) {
122 p = cadddr(tail);
123 min = cadr(p);
124 if (merge_chunk_p(&delta,max,min,&count,caddr(tail),car(p))) {
125 // It is mergeable.
126 widest = i+1; last = tail; c_count=count;
127 }
128 }
129 merge = list4(widest,merge,delta,c_count);
130 // skip merged chunks
131 list = cadr(last);
132 }
133 // last one can remain.
134 if (list) merge = list4(1,merge,caddr(list),car(cadddr(list)));
135 return merge;
136 }
137
138 static int
139 table_jump(int count,int delta,int cslist)
140 {
141 int list;
142 for(;count-->0;cslist=cadr(cslist)) {
143 list = car(cslist);
144 printf("# table cases delta=%d count=%d min=%d max=%d\n",
145 caddr(cslist),car(cadddr(cslist)),
146 cadr(cadddr(cslist)),caddr(cadddr(cslist))
147 );
148 for(;list; list=cadr(list)) {
149 if (caddr(list))
150 cmpdimm(car(list),csvalue1,caddr(list),0);
151 }
152 }
153 return cslist;
154 }
155
156 static int
157 cascade_compare(int count,int cslist)
158 {
159 int list;
160 for(;count-->0;cslist=cadr(cslist)) {
161 list = car(cslist);
162 printf("# cascade cases delta=%d count=%d min=%d max=%d\n",
163 caddr(cslist),car(cadddr(cslist)),
164 cadr(cadddr(cslist)),caddr(cadddr(cslist))
165 );
166 for(;list; list=cadr(list)) {
167 if (caddr(list))
168 cmpdimm(car(list),csvalue1,caddr(list),0);
169 // value register label mode
170 }
171 }
172 return cslist;
173 }
174
175 #define CASE_TABLE_COUNT 10
176 #define CASE_INDEX_COUNT 10
177
178
179 /*
180 generate index jmp
181 */
182
183 static void
184 switch_index_jmp(int index,int label)
185 {
186 int value = car(car(caddr(caddr(index))));
187 cmpdimm(value,csvalue1,label,LT);
188 // value register label mode
189 }
190
191 /*
192 generate leaf index branch
193 */
194
195 static int
196 switch_make_index_leaf(int count,int index)
197 {
198 for(;count-- !=0 && cadr(index);index=cadr(index)) {
199 switch_index_jmp(
200 cadr(index), /* next max */
201 car(caddr(index)) /*label*/ );
202 }
203 if (!cadr(index)) {
204 // don't check max boundary
205 jmp(car(caddr(index)));
206 return 0;
207 }
208 if (count!=0) error(-1);
209 return index;
210 }
211
212 /*
213 generate index switch branch (no table).
214 if necessary generate higher index.
215 */
216
217 static void
218 switch_make_index(int index0,int count,int cslabel)
219 {
220 int index=0;
221 int icount=0;
222 int l,min,max;
223 while (index0 && count > CASE_INDEX_COUNT) {
224 l = backdef();
225 min = index_min(index0);
226 index0=switch_make_index_leaf(CASE_INDEX_COUNT,index0);
227 max = index_min(index0);
228 index = list4(l,index,max,min);
229 count-=CASE_INDEX_COUNT;
230 icount++;
231 }
232 if (index) {
233 switch_make_index(reverse0(index),icount,cslabel);
234 if (dlabel) jmp(dlabel);
235 } else {
236 fwddef(cslabel);
237 switch_make_index_leaf(-1,index0);
238 if (dlabel) jmp(dlabel);
239 }
240 }
241
242 /*
243 generate leaf switch branch or table jump
244 */
245
246 static int
247 switch_leaf(int count,int merge,int cslist)
248 {
249 for(;count-- !=0 && merge;merge=cadr(merge)) {
250 printf("# merge count %d delta %d c_count %d\n",
251 car(merge),caddr(merge),cadddr(merge));
252 if (cadddr(merge)>CASE_TABLE_COUNT)
253 cslist = table_jump(car(merge),caddr(merge),cslist);
254 else
255 cslist = cascade_compare(car(merge),cslist);
256 }
257 return cslist;
258 }
259
260 /*
261 make index if necessary or
262 generate case branch or table jump
263 */
264
265 static void
266 switch_index(int merge,int chunks,int cslabel,int dlabel,int gmax)
267 {
268 int m,l,max,min;
269 int chnkcnt = 0;
270 int icount = 0;
271 int count = 0;
272 int index = 0;
273 for(m=merge;m;m=cadr(m)) {
274 chnkcnt++;
275 count += cadddr(m);
276 if (count > CASE_INDEX_COUNT || (index && !cadr(m))) {
277 icount++;
278 min = car(car(chunks));
279 l = backdef();
280 chunks= switch_leaf(chnkcnt,merge,chunks);
281 max = chunks?car(car(chunks)):gmax;
282 index = list4(l,index,max,min);
283 merge = cadr(m); count = 0; chnkcnt = 0;
284 if (dlabel) jmp(dlabel);
285 }
286 }
287 if (index) {
288 index = reverse0(index);
289 // check lower bound
290 switch_index_jmp(index,dlabel?dlabel:blabel);
291 switch_make_index(index,icount,cslabel);
292 if (dlabel) jmp(dlabel);
293 } else {
294 fwddef(cslabel);
295 switch_leaf(-1,merge,chunks);
296 if (dlabel) jmp(dlabel);
297 }
298 }
299
300 /* generate switch table, index, cascading branch */
301
302
303 void
304 genswitch(int cslist,int cslabel,int dlabel)
305 {
306 int chunks,merge,gmax;
307 int i,j;
308 #if 0
309 for(i=cslist;i;i=cadr(i)) {
310 printf("# case %d L_%d\n",car(i),caddr(i));
311 }
312 #endif
313 /* find stepwise chunks */
314 chunks=make_chunk(cslist);
315 #if 1
316 chunks = 0;
317 for(i=cslist;i;i=cadr(i)) {
318 chunks++;
319 }
320 j = chunks;
321 #endif
322 /* possible merge of loose stepwise chunks */
323 merge = merge_chunk(chunks);
324 #if 0
325 // chunks: list3(widest,next,delta);
326 printf("# chunks %d = sum ",j);
327 j = 0;
328 for(i=merge;i;i=cadr(i)) {
329 printf(" %d/%d",car(i),caddr(i));
330 j+=car(i);
331 }
332 printf(" sum = %d\n",j);
333 #endif
334 /* make index branch or table jump */
335 gmax = chunk_max(chunks);
336 chunks = reverse0(chunks);
337 switch_index(merge,chunks,cslabel,dlabel,gmax);
338 }
339
340 #endif
341
342
343
344 /* end */