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