xref: /plan9-contrib/sys/src/cmd/4l/noop.c (revision f8bc6aaf8056e137bcdfb6117a990ac3eff62cc9)
1 #include	"l.h"
2 
3 void
noops(void)4 noops(void)
5 {
6 	Prog *p, *p1, *q, *q1;
7 	int o, curframe, curbecome, maxbecome;
8 
9 	/*
10 	 * find leaf subroutines
11 	 * become sizes
12 	 * frame sizes
13 	 * strip NOPs
14 	 * expand RET
15 	 * expand BECOME pseudo
16 	 */
17 
18 	if(debug['v'])
19 		Bprint(&bso, "%5.2f noops\n", cputime());
20 	Bflush(&bso);
21 
22 	curframe = 0;
23 	curbecome = 0;
24 	maxbecome = 0;
25 	curtext = 0;
26 
27 	q = P;
28 	for(p = firstp; p != P; p = p->link) {
29 
30 		/* find out how much arg space is used in this TEXT */
31 		if(p->to.type == D_OREG && p->to.reg == REGSP)
32 			if(p->to.offset > curframe)
33 				curframe = p->to.offset;
34 
35 		switch(p->as) {
36 		case ATEXT:
37 			if(curtext && curtext->from.sym) {
38 				curtext->from.sym->frame = curframe;
39 				curtext->from.sym->become = curbecome;
40 				if(curbecome > maxbecome)
41 					maxbecome = curbecome;
42 			}
43 			curframe = 0;
44 			curbecome = 0;
45 
46 			p->mark |= LABEL|LEAF|SYNC;
47 			if(p->link)
48 				p->link->mark |= LABEL;
49 			curtext = p;
50 			break;
51 
52 		/* too hard, just leave alone */
53 		case AMOVW:
54 		case AMOVV:
55 			if(p->to.type == D_FCREG ||
56 			   p->to.type == D_MREG) {
57 				p->mark |= LABEL|SYNC;
58 				break;
59 			}
60 			if(p->from.type == D_FCREG ||
61 			   p->from.type == D_MREG) {
62 				p->mark |= LABEL|SYNC;
63 				addnop(p);
64 				addnop(p);
65 				nop.mfrom.count += 2;
66 				nop.mfrom.outof += 2;
67 				break;
68 			}
69 			break;
70 
71 		/* too hard, just leave alone */
72 		case ACASE:
73 		case ASYSCALL:
74 		case AWORD:
75 		case ATLBWR:
76 		case ATLBWI:
77 		case ATLBP:
78 		case ATLBR:
79 			p->mark |= LABEL|SYNC;
80 			break;
81 
82 		case ANOR:
83 			if(p->to.type == D_REG && p->to.reg == REGZERO)
84 				p->mark |= LABEL|SYNC;
85 			break;
86 
87 		case ARET:
88 			/* special form of RET is BECOME */
89 			if(p->from.type == D_CONST)
90 				if(p->from.offset > curbecome)
91 					curbecome = p->from.offset;
92 
93 			if(p->link != P)
94 				p->link->mark |= LABEL;
95 			break;
96 
97 		case ANOP:
98 			q1 = p->link;
99 			q->link = q1;		/* q is non-nop */
100 			q1->mark |= p->mark;
101 			continue;
102 
103 		case ABCASE:
104 			p->mark |= LABEL|SYNC;
105 			goto dstlab;
106 
107 		case ABGEZAL:
108 		case ABLTZAL:
109 		case AJAL:
110 			if(curtext != P)
111 				curtext->mark &= ~LEAF;
112 
113 		case AJMP:
114 		case ABEQ:
115 		case ABGEZ:
116 		case ABGTZ:
117 		case ABLEZ:
118 		case ABLTZ:
119 		case ABNE:
120 		case ABFPT:
121 		case ABFPF:
122 			p->mark |= BRANCH;
123 
124 		dstlab:
125 			q1 = p->cond;
126 			if(q1 != P) {
127 				while(q1->as == ANOP) {
128 					q1 = q1->link;
129 					p->cond = q1;
130 				}
131 				if(!(q1->mark & LEAF))
132 					q1->mark |= LABEL;
133 			} else
134 				p->mark |= LABEL;
135 			q1 = p->link;
136 			if(q1 != P)
137 				q1->mark |= LABEL;
138 			break;
139 		}
140 		q = p;
141 	}
142 
143 	if(curtext && curtext->from.sym) {
144 		curtext->from.sym->frame = curframe;
145 		curtext->from.sym->become = curbecome;
146 		if(curbecome > maxbecome)
147 			maxbecome = curbecome;
148 	}
149 
150 	if(debug['b'])
151 		print("max become = %d\n", maxbecome);
152 	xdefine("ALEFbecome", STEXT, maxbecome);
153 
154 	curtext = 0;
155 	for(p = firstp; p != P; p = p->link) {
156 		switch(p->as) {
157 		case ATEXT:
158 			curtext = p;
159 			break;
160 		case AJAL:
161 			if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) {
162 				o = maxbecome - curtext->from.sym->frame;
163 				if(o <= 0)
164 					break;
165 				/* calling a become or calling a variable */
166 				if(p->to.sym == S || p->to.sym->become) {
167 					curtext->to.offset += o;
168 					if(debug['b']) {
169 						curp = p;
170 						print("%D calling %D increase %d\n",
171 							&curtext->from, &p->to, o);
172 					}
173 				}
174 			}
175 			break;
176 		}
177 	}
178 
179 	for(p = firstp; p != P; p = p->link) {
180 		o = p->as;
181 		switch(o) {
182 		case ATEXT:
183 			curtext = p;
184 			autosize = p->to.offset + 8;
185 			if(autosize <= 8)
186 			if(curtext->mark & LEAF) {
187 				p->to.offset = -8;
188 				autosize = 0;
189 			}
190 
191 			q = p;
192 			if(autosize) {
193 				if(autosize & 7)
194 					Bprint(&bso, "odd stack in: %s\n",
195 						curtext->from.sym->name);
196 				q = prg();
197 				q->as = AADDV;
198 				q->line = p->line;
199 				q->from.type = D_CONST;
200 				q->from.offset = -autosize;
201 				q->to.type = D_REG;
202 				q->to.reg = REGSP;
203 
204 				q->link = p->link;
205 				p->link = q;
206 			} else
207 			if(!(curtext->mark & LEAF)) {
208 				if(debug['v'])
209 					Bprint(&bso, "save suppressed in: %s\n",
210 						curtext->from.sym->name);
211 				Bflush(&bso);
212 				curtext->mark |= LEAF;
213 			}
214 
215 			if(curtext->mark & LEAF) {
216 				if(curtext->from.sym)
217 					curtext->from.sym->type = SLEAF;
218 				break;
219 			}
220 
221 			q1 = prg();
222 			q1->as = AMOVV;
223 			q1->line = p->line;
224 			q1->from.type = D_REG;
225 			q1->from.reg = REGLINK;
226 			q1->to.type = D_OREG;
227 			q1->from.offset = 0;
228 			q1->to.reg = REGSP;
229 
230 			q1->link = q->link;
231 			q->link = q1;
232 			break;
233 
234 		case ARET:
235 			nocache(p);
236 			if(p->from.type == D_CONST)
237 				goto become;
238 			if(curtext->mark & LEAF) {
239 				if(!autosize) {
240 					p->as = AJMP;
241 					p->from = zprg.from;
242 					p->to.type = D_OREG;
243 					p->to.offset = 0;
244 					p->to.reg = REGLINK;
245 					p->mark |= BRANCH;
246 					break;
247 				}
248 
249 				p->as = AADDV;
250 				p->from.type = D_CONST;
251 				p->from.offset = autosize;
252 				p->to.type = D_REG;
253 				p->to.reg = REGSP;
254 
255 				q = prg();
256 				q->as = AJMP;
257 				q->line = p->line;
258 				q->to.type = D_OREG;
259 				q->to.offset = 0;
260 				q->to.reg = REGLINK;
261 				q->mark |= BRANCH;
262 
263 				q->link = p->link;
264 				p->link = q;
265 				break;
266 			}
267 			p->as = AMOVV;
268 			p->from.type = D_OREG;
269 			p->from.offset = 0;
270 			p->from.reg = REGSP;
271 			p->to.type = D_REG;
272 			p->to.reg = 2;
273 
274 			q = p;
275 			if(autosize) {
276 				q = prg();
277 				q->as = AADDV;
278 				q->line = p->line;
279 				q->from.type = D_CONST;
280 				q->from.offset = autosize;
281 				q->to.type = D_REG;
282 				q->to.reg = REGSP;
283 
284 				q->link = p->link;
285 				p->link = q;
286 			}
287 
288 			q1 = prg();
289 			q1->as = AJMP;
290 			q1->line = p->line;
291 			q1->to.type = D_OREG;
292 			q1->to.offset = 0;
293 			q1->to.reg = 2;
294 			q1->mark |= BRANCH;
295 
296 			q1->link = q->link;
297 			q->link = q1;
298 			break;
299 
300 		become:
301 			if(curtext->mark & LEAF) {
302 
303 				q = prg();
304 				q->line = p->line;
305 				q->as = AJMP;
306 				q->from = zprg.from;
307 				q->to = p->to;
308 				q->cond = p->cond;
309 				q->link = p->link;
310 				q->mark |= BRANCH;
311 				p->link = q;
312 
313 				p->as = AADDV;
314 				p->from = zprg.from;
315 				p->from.type = D_CONST;
316 				p->from.offset = autosize;
317 				p->to = zprg.to;
318 				p->to.type = D_REG;
319 				p->to.reg = REGSP;
320 
321 				break;
322 			}
323 			q = prg();
324 			q->line = p->line;
325 			q->as = AJMP;
326 			q->from = zprg.from;
327 			q->to = p->to;
328 			q->cond = p->cond;
329 			q->link = p->link;
330 			q->mark |= BRANCH;
331 			p->link = q;
332 
333 			q = prg();
334 			q->line = p->line;
335 			q->as = AADDV;
336 			q->from.type = D_CONST;
337 			q->from.offset = autosize;
338 			q->to.type = D_REG;
339 			q->to.reg = REGSP;
340 			q->link = p->link;
341 			p->link = q;
342 
343 			p->as = AMOVV;
344 			p->from = zprg.from;
345 			p->from.type = D_OREG;
346 			p->from.offset = 0;
347 			p->from.reg = REGSP;
348 			p->to = zprg.to;
349 			p->to.type = D_REG;
350 			p->to.reg = REGLINK;
351 
352 			break;
353 		}
354 	}
355 
356 	curtext = P;
357 	q = P;		/* p - 1 */
358 	q1 = firstp;	/* top of block */
359 	o = 0;		/* count of instructions */
360 	for(p = firstp; p != P; p = p1) {
361 		p1 = p->link;
362 		o++;
363 		if(p->mark & NOSCHED){
364 			if(q1 != p){
365 				sched(q1, q);
366 			}
367 			for(; p != P; p = p->link){
368 				if(!(p->mark & NOSCHED))
369 					break;
370 				q = p;
371 			}
372 			p1 = p;
373 			q1 = p;
374 			o = 0;
375 			continue;
376 		}
377 		if(p->mark & (LABEL|SYNC)) {
378 			if(q1 != p)
379 				sched(q1, q);
380 			q1 = p;
381 			o = 1;
382 		}
383 		if(p->mark & (BRANCH|SYNC)) {
384 			sched(q1, p);
385 			q1 = p1;
386 			o = 0;
387 		}
388 		if(o >= NSCHED) {
389 			sched(q1, p);
390 			q1 = p1;
391 			o = 0;
392 		}
393 		q = p;
394 	}
395 }
396 
397 void
addnop(Prog * p)398 addnop(Prog *p)
399 {
400 	Prog *q;
401 
402 	q = prg();
403 	q->as = ANOR;
404 	q->line = p->line;
405 	q->from.type = D_REG;
406 	q->from.reg = REGZERO;
407 	q->to.type = D_REG;
408 	q->to.reg = REGZERO;
409 
410 	q->link = p->link;
411 	p->link = q;
412 }
413 
414 void
nocache(Prog * p)415 nocache(Prog *p)
416 {
417 	p->optab = 0;
418 	p->from.class = 0;
419 	p->to.class = 0;
420 }
421