xref: /plan9-contrib/sys/src/cmd/il/noop.c (revision ce95e1b3727b9cb1c223ffbed69aff21a8ced255)
1 #include	"l.h"
2 
3 void
noops(void)4 noops(void)
5 {
6 	Prog *p, *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 AMOV:
55 			if(p->to.type == D_CTLREG) {
56 				p->mark |= LABEL|SYNC;
57 				break;
58 			}
59 			if(p->from.type == D_CTLREG) {
60 				p->mark |= LABEL|SYNC;
61 				break;
62 			}
63 			break;
64 
65 		/* too hard, just leave alone */
66 		case ASYS:
67 		case AWORD:
68 			p->mark |= LABEL|SYNC;
69 			break;
70 
71 		case ARET:
72 			/* special form of RET is BECOME */
73 			if(p->from.type == D_CONST)
74 				if(p->from.offset > curbecome)
75 					curbecome = p->from.offset;
76 
77 			if(p->link != P)
78 				p->link->mark |= LABEL;
79 			break;
80 
81 		case ANOP:
82 			q1 = p->link;
83 			q->link = q1;		/* q is non-nop */
84 			q1->mark |= p->mark;
85 			continue;
86 
87 		case AJAL:
88 			if(curtext != P)
89 				curtext->mark &= ~LEAF;
90 
91 		case AJMP:
92 		case ABEQ:
93 		case ABGE:
94 		case ABGEU:
95 		case ABLT:
96 		case ABLTU:
97 		case ABNE:
98 			p->mark |= BRANCH;
99 
100 			q1 = p->cond;
101 			if(q1 != P) {
102 				while(q1->as == ANOP) {
103 					q1 = q1->link;
104 					p->cond = q1;
105 				}
106 				if(!(q1->mark & LEAF))
107 					q1->mark |= LABEL;
108 			} else
109 				p->mark |= LABEL;
110 			q1 = p->link;
111 			if(q1 != P)
112 				q1->mark |= LABEL;
113 			break;
114 		}
115 		q = p;
116 	}
117 
118 	if(curtext && curtext->from.sym) {
119 		curtext->from.sym->frame = curframe;
120 		curtext->from.sym->become = curbecome;
121 		if(curbecome > maxbecome)
122 			maxbecome = curbecome;
123 	}
124 
125 	if(debug['b'])
126 		print("max become = %d\n", maxbecome);
127 	xdefine("ALEFbecome", STEXT, maxbecome);
128 
129 	curtext = 0;
130 	for(p = firstp; p != P; p = p->link) {
131 		switch(p->as) {
132 		case ATEXT:
133 			curtext = p;
134 			break;
135 		case AJAL:
136 			if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) {
137 				o = maxbecome - curtext->from.sym->frame;
138 				if(o <= 0)
139 					break;
140 				/* calling a become or calling a variable */
141 				if(p->to.sym == S || p->to.sym->become) {
142 					curtext->to.offset += o;
143 					if(debug['b']) {
144 						curp = p;
145 						print("%D calling %D increase %d\n",
146 							&curtext->from, &p->to, o);
147 					}
148 				}
149 			}
150 			break;
151 		}
152 	}
153 
154 	for(p = firstp; p != P; p = p->link) {
155 		o = p->as;
156 		switch(o) {
157 		case ATEXT:
158 			curtext = p;
159 			autosize = p->to.offset + ptrsize;
160 			if(autosize <= ptrsize) {
161 				if(curtext->mark & LEAF || autosize <= 0) {
162 					p->to.offset = -ptrsize;
163 					autosize = 0;
164 				} else if(ptrsize == 4) {
165 					p->to.offset = 4;
166 					autosize = 8;
167 				}
168 			}
169 
170 			q = p;
171 			if(autosize) {
172 				q = prg();
173 				q->as = AADD;
174 				q->line = p->line;
175 				q->from.type = D_CONST;
176 				q->from.offset = -autosize;
177 				q->to.type = D_REG;
178 				q->to.reg = REGSP;
179 
180 				q->link = p->link;
181 				p->link = q;
182 			} else
183 			if(!(curtext->mark & LEAF)) {
184 				if(debug['v'])
185 					Bprint(&bso, "save suppressed in: %s\n",
186 						curtext->from.sym->name);
187 				Bflush(&bso);
188 				curtext->mark |= LEAF;
189 			}
190 
191 			if(curtext->mark & LEAF) {
192 				if(curtext->from.sym)
193 					curtext->from.sym->type = SLEAF;
194 				break;
195 			}
196 
197 			q1 = prg();
198 			q1->as = thechar == 'j' ? AMOV : AMOVW;
199 			q1->line = p->line;
200 			q1->from.type = D_REG;
201 			q1->from.reg = REGLINK;
202 			q1->to.type = D_OREG;
203 			q1->from.offset = 0;
204 			q1->to.reg = REGSP;
205 
206 			q1->link = q->link;
207 			q->link = q1;
208 			break;
209 
210 		case ARET:
211 			nocache(p);
212 			if(p->from.type == D_CONST)
213 				goto become;
214 			if(curtext->mark & LEAF) {
215 				if(!autosize) {
216 					p->as = AJMP;
217 					p->from = zprg.from;
218 					p->to.type = D_OREG;
219 					p->to.offset = 0;
220 					p->to.reg = REGLINK;
221 					p->mark |= BRANCH;
222 					break;
223 				}
224 
225 				p->as = AADD;
226 				p->from.type = D_CONST;
227 				p->from.offset = autosize;
228 				p->to.type = D_REG;
229 				p->to.reg = REGSP;
230 
231 				q = prg();
232 				q->as = AJMP;
233 				q->line = p->line;
234 				q->to.type = D_OREG;
235 				q->to.offset = 0;
236 				q->to.reg = REGLINK;
237 				q->mark |= BRANCH;
238 
239 				q->link = p->link;
240 				p->link = q;
241 				break;
242 			}
243 			p->as = thechar == 'j' ? AMOV : AMOVW;
244 			p->from.type = D_OREG;
245 			p->from.offset = 0;
246 			p->from.reg = REGSP;
247 			p->to.type = D_REG;
248 			p->to.reg = REGLINK;
249 
250 			q = p;
251 			if(autosize) {
252 				q = prg();
253 				q->as = AADD;
254 				q->line = p->line;
255 				q->from.type = D_CONST;
256 				q->from.offset = autosize;
257 				q->to.type = D_REG;
258 				q->to.reg = REGSP;
259 
260 				q->link = p->link;
261 				p->link = q;
262 			}
263 
264 			q1 = prg();
265 			q1->as = AJMP;
266 			q1->line = p->line;
267 			q1->to.type = D_OREG;
268 			q1->to.offset = 0;
269 			q1->to.reg = REGLINK;
270 			q1->mark |= BRANCH;
271 
272 			q1->link = q->link;
273 			q->link = q1;
274 			break;
275 
276 		become:
277 			if(curtext->mark & LEAF) {
278 
279 				q = prg();
280 				q->line = p->line;
281 				q->as = AJMP;
282 				q->from = zprg.from;
283 				q->to = p->to;
284 				q->cond = p->cond;
285 				q->link = p->link;
286 				q->mark |= BRANCH;
287 				p->link = q;
288 
289 				p->as = AADD;
290 				p->from = zprg.from;
291 				p->from.type = D_CONST;
292 				p->from.offset = autosize;
293 				p->to = zprg.to;
294 				p->to.type = D_REG;
295 				p->to.reg = REGSP;
296 
297 				break;
298 			}
299 			q = prg();
300 			q->line = p->line;
301 			q->as = AJMP;
302 			q->from = zprg.from;
303 			q->to = p->to;
304 			q->cond = p->cond;
305 			q->link = p->link;
306 			q->mark |= BRANCH;
307 			p->link = q;
308 
309 			q = prg();
310 			q->line = p->line;
311 			q->as = AADD;
312 			q->from.type = D_CONST;
313 			q->from.offset = autosize;
314 			q->to.type = D_REG;
315 			q->to.reg = REGSP;
316 			q->link = p->link;
317 			p->link = q;
318 
319 			p->as = thechar == 'j' ? AMOV : AMOVW;
320 			p->from = zprg.from;
321 			p->from.type = D_OREG;
322 			p->from.offset = 0;
323 			p->from.reg = REGSP;
324 			p->to = zprg.to;
325 			p->to.type = D_REG;
326 			p->to.reg = REGLINK;
327 
328 			break;
329 		}
330 	}
331 
332 	curtext = P;
333 }
334 
335 void
nocache(Prog * p)336 nocache(Prog *p)
337 {
338 	p->optab = 0;
339 	p->from.class = 0;
340 	p->to.class = 0;
341 }
342