1 /*-----------------------------------------------------------------
2 SDCClabel.c - label optimizations on iCode (intermediate code)
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
27 hTab *labelRef = NULL;
28 hTab *labelDef = NULL;
30 /*-----------------------------------------------------------------*/
31 /* buildLabelRefTable - creates an hashTable of label references */
32 /*-----------------------------------------------------------------*/
34 buildLabelRefTable (iCode * ic)
38 setToNull ((void *) &labelRef);
39 setToNull ((void *) &labelDef);
40 labelRef = newHashTable (labelKey + 1);
41 labelDef = newHashTable (labelKey + 1);
43 for (lic = ic; lic; lic = lic->next)
46 hTabAddItem (&labelRef, (IC_LABEL (lic))->key, lic);
48 if (lic->op == JUMPTABLE)
51 for (lbl = setFirstItem (IC_JTLABELS (lic)); lbl;
52 lbl = setNextItem (IC_JTLABELS (lic)))
54 hTabAddItem (&labelRef, lbl->key, lic);
61 hTabAddItem (&labelRef, (IC_TRUE (lic))->key, lic);
63 hTabAddItem (&labelRef, (IC_FALSE (lic))->key, lic);
66 hTabAddItem (&labelDef, (IC_LABEL (lic))->key, lic);
71 /*-----------------------------------------------------------------*/
72 /* labelGotoNext - kills gotos to next statement */
73 /*-----------------------------------------------------------------*/
75 labelGotoNext (iCode * ic)
80 for (loop = ic; loop; loop = loop->next)
83 if (loop->op == GOTO && /* if this is a goto */
84 loop->next && /* and we have a next one */
85 loop->next->op == LABEL && /* next one is a label */
86 loop->next->label->key == loop->label->key) /* same label */
88 loop->prev->next = loop->next; /* get this out of the chain */
89 loop->next->prev = loop->prev;
90 hTabDeleteItem (&labelRef, (IC_LABEL (loop))->key, loop, DELETE_ITEM, NULL);
98 /*-------------------------------------------------------------------*/
99 /* deleteIfx - delete an IFX iCode or convert to DUMMY_READ_VOLATILE */
100 /*-------------------------------------------------------------------*/
102 deleteIfx (iCode * loop, int key)
104 if (!options.lessPedantic)
106 werrorfl (loop->filename, loop->lineno, W_CONTROL_FLOW);
108 hTabDeleteItem (&labelRef, key, loop, DELETE_ITEM, NULL);
110 /* If the condition was volatile, convert IFX to */
111 /* DUMMY_READ_VOLATILE. Otherwise just delete the */
113 if (IS_OP_VOLATILE (IC_COND (loop)))
115 IC_RIGHT (loop) = IC_COND (loop);
116 IC_LEFT (loop) = NULL;
117 IC_RESULT (loop) = NULL;
118 loop->op = DUMMY_READ_VOLATILE;
122 loop->prev->next = loop->next;
123 loop->next->prev = loop->prev;
128 /*-----------------------------------------------------------------*/
129 /* labelIfx - special case Ifx elimination */
130 /*-----------------------------------------------------------------*/
132 labelIfx (iCode * ic)
138 for (loop = ic; loop; loop = loop->next)
140 /* if condition goto label */
142 /* i.e. the flow is going to the same location
143 regardless of the condition in this case the
144 condition can be eliminated with a WARNING ofcource */
145 if (loop->op == IFX &&
147 loop->next->op == GOTO)
149 if (IC_TRUE (loop) &&
150 IC_TRUE (loop)->key == IC_LABEL (loop->next)->key)
152 deleteIfx (loop, IC_TRUE (loop)->key);
158 if (IC_FALSE (loop) &&
159 IC_FALSE (loop)->key == IC_LABEL (loop->next)->key)
161 deleteIfx (loop, IC_FALSE (loop)->key);
167 /* same as above but with a twist */
168 /* if condition goto label */
170 if (loop->op == IFX &&
172 loop->next->op == LABEL &&
173 ((IC_TRUE (loop) && IC_TRUE (loop)->key == IC_LABEL (loop->next)->key) ||
174 (IC_FALSE (loop) && IC_FALSE (loop)->key == IC_LABEL (loop->next)->key)))
176 deleteIfx (loop, IC_LABEL (loop->next)->key);
181 /* we will eliminate certain special case situations */
182 /* of the conditional statement :- */
183 /* if cond != 0 goto _trueLabel */
184 /* goto _falseLabel */
187 /* in these cases , if this is the only reference */
188 /* to the _trueLabel, we can change it to :- */
189 /* if cond == 0 goto _falseLabel */
191 /* similarly if we have a situation like :- */
192 /* if cond == 0 goto _falseLabel */
193 /* goto _someLabel */
195 /* we can change this to */
196 /* if cond != 0 goto _someLabel */
198 if (loop->op == IFX &&
200 loop->next->op == GOTO &&
202 loop->next->next->op == LABEL)
206 /* now check that the last label is the */
207 /* same as the _trueLabel of this */
209 if ((IC_TRUE (loop))->key != (IC_LABEL (loop->next->next))->key)
212 else if ((IC_FALSE (loop))->key != (IC_LABEL (loop->next->next))->key)
215 /* now make sure that this is the only */
216 /* referenece to the _trueLabel */
217 if (IC_TRUE (loop) && hTabItemWithKey (labelRef, (IC_TRUE (loop))->key))
220 /* we just change the falseLabel */
221 /* to the next goto statement */
222 /* unreferenced label will take */
223 /* care of removing the label */
224 /* delete reference to the true label */
226 hTabDeleteItem (&labelRef, (IC_TRUE (loop))->key, loop, DELETE_ITEM, NULL);
227 IC_TRUE (loop) = NULL;
228 IC_FALSE (loop) = IC_LABEL (loop->next);
229 /* add reference to the LABEL */
230 hTabAddItem (&labelRef, (IC_FALSE (loop))->key, loop);
231 /* next remove the goto */
232 hTabDeleteItem (&labelRef,
233 (IC_LABEL (loop->next))->key, loop->next, DELETE_ITEM, NULL);
234 loop->next = loop->next->next;
235 loop->next->prev = loop;
240 /* now do the same with the false labels */
241 if (IC_FALSE (loop) &&
242 hTabItemWithKey (labelRef, (IC_FALSE (loop))->key))
245 hTabDeleteItem (&labelRef, (IC_FALSE (loop))->key, loop, DELETE_ITEM, NULL);
246 IC_FALSE (loop) = NULL;
247 IC_TRUE (loop) = IC_LABEL (loop->next);
248 hTabAddItem (&labelRef, (IC_TRUE (loop))->key, loop);
249 hTabDeleteItem (&labelRef, (IC_LABEL (loop->next))->key, loop->next, DELETE_ITEM, NULL);
250 loop->next = loop->next->next;
251 loop->next->prev = loop;
261 /*-----------------------------------------------------------------*/
262 /* labelGotoGoto - target of a goto is a goto */
263 /*-----------------------------------------------------------------*/
265 labelGotoGoto (iCode * ic)
270 for (loop = ic; loop; loop = loop->next)
273 symbol *sLabel = NULL;
277 case GOTO: /* for a goto statement */
278 stat = hTabItemWithKey (labelDef, (sLabel = IC_LABEL (loop))->key);
280 case IFX: /* for a conditional jump */
282 stat = hTabItemWithKey (labelDef, (sLabel = IC_TRUE (loop))->key);
284 stat = hTabItemWithKey (labelDef, (sLabel = IC_FALSE (loop))->key);
287 /* if we have a target statement then check if the next */
288 /* one is a goto: this means target of goto is a goto */
289 if (stat && stat->next &&
290 (stat->next->op == GOTO ||
291 stat->next->op == LABEL) &&
295 symbol *repLabel = stat->next->label; /* replace with label */
297 /* if they are the same then continue */
298 if (repLabel->key == sLabel->key)
301 /* replacement depends on the statement type */
305 case GOTO: /* for a goto statement */
307 hTabDeleteItem (&labelRef, (IC_LABEL (loop))->key, loop, DELETE_ITEM, NULL);
308 loop->label = repLabel;
309 hTabAddItem (&labelRef, repLabel->key, loop);
312 case IFX: /* for a conditional jump */
316 hTabDeleteItem (&labelRef, (IC_TRUE (loop))->key, loop, DELETE_ITEM, NULL);
317 IC_TRUE (loop) = repLabel;
322 hTabDeleteItem (&labelRef, (IC_FALSE (loop))->key, loop, DELETE_ITEM, NULL);
323 IC_FALSE (loop) = repLabel;
325 hTabAddItem (&labelRef, repLabel->key, loop);
335 /*-----------------------------------------------------------------*/
336 /* labelUnrefLabel - remove unreferenced labels */
337 /*-----------------------------------------------------------------*/
339 labelUnrefLabel (iCode * ic)
344 for (loop = ic; loop; loop = loop->next)
347 /* if this is a label */
348 if (loop->op == LABEL)
350 if (((IC_LABEL (loop))->key == returnLabel->key) ||
351 ((IC_LABEL (loop))->key == entryLabel->key))
354 if (hTabItemWithKey (labelRef, (IC_LABEL (loop))->key))
357 /* else eliminitate this one */
358 loop->prev->next = loop->next; /* get this out of the chain */
359 loop->next->prev = loop->prev;
367 /*-----------------------------------------------------------------*/
368 /* labelUnreach - remove unreachable code */
369 /*-----------------------------------------------------------------*/
371 labelUnreach (iCode * ic)
377 /* if we hit a return statement or a goto statement */
378 /* remove all statements till we hit the next label */
379 for (loop = ic; loop; loop = loop->next)
383 /* found a goto || return && the next */
384 /* statement is not a label */
385 if (loop->op == GOTO || loop->op == RETURN)
390 (loop->next->op == LABEL ||
391 loop->next->op == ENDFUNCTION))
394 /* loop till we find a label */
396 while (loop2 && loop2->op != LABEL)
399 /* throw away those in between */
400 for (tic = loop->next; tic && tic != loop2; tic = tic->next)
402 /* remove label references if any */
406 hTabDeleteItem (&labelRef, IC_LABEL (tic)->key, tic, DELETE_ITEM, NULL);
411 hTabDeleteItem (&labelRef, IC_TRUE (tic)->key, tic, DELETE_ITEM, NULL);
413 hTabDeleteItem (&labelRef, IC_FALSE (tic)->key, tic, DELETE_ITEM, NULL);
422 werrorfl (loop->next->filename, loop->next->lineno,
425 /* now set up the pointers */
435 /*-----------------------------------------------------------------*/
436 /* iCodeLabelOptimize - some obvious & general optimizations */
437 /*-----------------------------------------------------------------*/
439 iCodeLabelOptimize (iCode * ic)
441 if (!optimize.label1 &&
447 /* build labelreferences */
448 buildLabelRefTable (ic);
450 /* the following transformations need to ne done */
451 /* repeatedly till a fixed point is reached */
457 /* first eliminate any goto statement */
458 /* that goes to the next statement */
460 change += labelGotoNext (ic);
463 change += labelIfx (ic);
465 /* target of a goto is a goto then rename this goto */
467 change += labelGotoGoto (ic);
469 /* remove unreference labels */
471 change += labelUnrefLabel (ic);
473 /* remove unreachable code */
474 change += labelUnreach (ic);
476 if (!change) /* fixed point reached */