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 -------------------------------------------------------------------------*/
26 #include "SDCCglobl.h"
30 #include "SDCChasht.h"
33 #include "SDCCicode.h"
34 #include "SDCClabel.h"
36 hTab *labelRef = NULL ;
37 hTab *labelDef = NULL ;
39 /*-----------------------------------------------------------------*/
40 /* buildLabelRefTable - creates an hashTable of label referneces */
41 /*-----------------------------------------------------------------*/
42 void buildLabelRefTable (iCode *ic)
46 setToNull ((void **)&labelRef);
47 setToNull ((void **)&labelDef);
48 labelRef = newHashTable(labelKey + 1);
49 labelDef = newHashTable(labelKey + 1);
51 for (lic = ic ; lic ; lic = lic->next ) {
52 if ( lic->op == GOTO )
53 hTabAddItem (&labelRef, (IC_LABEL(lic))->key, lic);
55 if ( lic->op == JUMPTABLE ) {
57 for (lbl = setFirstItem(IC_JTLABELS(lic)); lbl;
58 lbl = setNextItem(IC_JTLABELS(lic))) {
59 hTabAddItem(&labelRef,lbl->key,lic);
63 if (lic->op == IFX ) {
65 hTabAddItem(&labelRef,(IC_TRUE(lic))->key, lic);
67 hTabAddItem(&labelRef,(IC_FALSE(lic))->key, lic);
69 if ( lic->op == LABEL )
70 hTabAddItem (&labelDef,(IC_LABEL(lic))->key, lic);
75 /*-----------------------------------------------------------------*/
76 /* labelGotoNext - kills gotos to next statement */
77 /*-----------------------------------------------------------------*/
78 int labelGotoNext (iCode *ic)
83 for ( loop = ic ; loop ; loop = loop->next) {
85 if (loop->op == GOTO && /* if this is a goto */
86 loop->next && /* and we have a next one */
87 loop->next->op == LABEL && /* next one is a label */
88 loop->next->argLabel.label->key == loop->argLabel.label->key) /* same label */
90 loop->prev->next = loop->next ; /* get this out of the chain */
91 loop->next->prev = loop->prev ;
92 hTabDeleteItem (&labelRef,(IC_LABEL(loop))->key, loop, DELETE_ITEM, NULL);
100 /*-----------------------------------------------------------------*/
101 /* labelIfx - special case Ifx elimination */
102 /*-----------------------------------------------------------------*/
103 int labelIfx ( iCode *ic)
109 for ( loop = ic ; loop ; loop = loop->next ) {
110 /* if condition goto label */
112 /* i.e. the flow is going to the same location
113 regardless of the condition in this case the
114 condition can be eliminated with a WARNING ofcource */
115 if ( loop->op == IFX &&
117 loop->next->op == GOTO ) {
119 IC_TRUE(loop)->key == IC_LABEL(loop->next)->key) {
121 /* get rid of this if */
122 werror(W_CONTROL_FLOW,loop->filename,loop->lineno);
123 loop->prev->next = loop->next;
124 loop->next->prev = loop->prev;
125 hTabDeleteItem(&labelRef,
126 (IC_TRUE(loop))->key,
127 loop, DELETE_ITEM,NULL);
132 if (IC_FALSE(loop) &&
133 IC_FALSE(loop)->key == IC_LABEL(loop->next)->key){
134 /* get rid of this if */
135 werror(W_CONTROL_FLOW,loop->filename,loop->lineno);
136 loop->prev->next = loop->next;
137 loop->next->prev = loop->prev;
138 hTabDeleteItem(&labelRef,
139 (IC_FALSE(loop))->key,
140 loop, DELETE_ITEM,NULL);
146 /* same as above but with a twist */
147 /* if condition goto label */
149 if (loop->op == IFX &&
151 loop->next->op == LABEL &&
152 ((IC_TRUE(loop) && IC_TRUE(loop)->key == IC_LABEL(loop->next)->key) ||
153 (IC_FALSE(loop) && IC_FALSE(loop)->key == IC_LABEL(loop->next)->key))) {
155 werror(W_CONTROL_FLOW,loop->filename,loop->lineno);
156 loop->prev->next = loop->next;
157 loop->next->prev = loop->prev;
158 hTabDeleteItem(&labelRef,
159 IC_LABEL(loop->next)->key,
160 loop, DELETE_ITEM,NULL);
165 /* we will eliminate certain special case situations*/
166 /* of the conditional statement :- */
167 /* if cond != 0 goto _trueLabel */
168 /* goto _falseLabel */
171 /* in these cases , if this is the only reference */
172 /* to the _trueLabel, we can change it to :- */
173 /* if cond == 0 goto _falseLabel */
175 /* similarly if we have a situation like :- */
176 /* if cond == 0 goto _falseLabel */
177 /* goto _someLabel */
179 /* we can change this to */
180 /* if cond != 0 goto _someLabel */
182 if (loop->op == IFX &&
184 loop->next->op == GOTO &&
186 loop->next->next->op == LABEL ) {
189 /* now check that the last label is the */
190 /* same as the _trueLabel of this */
192 if ( (IC_TRUE(loop))->key != (IC_LABEL(loop->next->next))->key )
196 if ( (IC_FALSE(loop))->key != (IC_LABEL(loop->next->next))->key )
199 /* now make sure that this is the only */
200 /* referenece to the _trueLabel */
201 if ( IC_TRUE(loop) && hTabItemWithKey(labelRef,(IC_TRUE(loop))->key) ) {
203 /* we just change the falseLabel */
204 /* to the next goto statement */
205 /* unreferenced label will take */
206 /* care of removing the label */
207 /* delete reference to the true label */
209 hTabDeleteItem(&labelRef, (IC_TRUE(loop))->key, loop, DELETE_ITEM,NULL);
210 IC_TRUE(loop) = NULL ;
211 IC_FALSE(loop) = IC_LABEL(loop->next);
212 /* add reference to the LABEL */
213 hTabAddItem (&labelRef,(IC_FALSE(loop))->key,loop);
214 /* next remove the goto */
215 hTabDeleteItem(&labelRef,
216 (IC_LABEL(loop->next))->key,loop->next,DELETE_ITEM,NULL);
217 loop->next = loop->next->next ;
218 loop->next->prev = loop ;
223 /* now do the same with the false labels */
224 if (IC_FALSE(loop) &&
225 hTabItemWithKey(labelRef,(IC_FALSE(loop))->key)) {
227 hTabDeleteItem(&labelRef, (IC_FALSE(loop))->key, loop, DELETE_ITEM,NULL);
228 IC_FALSE(loop) = NULL ;
229 IC_TRUE(loop) = IC_LABEL(loop->next);
230 hTabAddItem (&labelRef,(IC_TRUE(loop))->key,loop);
231 hTabDeleteItem(&labelRef,(IC_LABEL(loop->next))->key,loop->next,DELETE_ITEM,NULL);
232 loop->next = loop->next->next ;
233 loop->next->prev = loop ;
243 /*-----------------------------------------------------------------*/
244 /* labelGotoGoto - target of a goto is a goto */
245 /*-----------------------------------------------------------------*/
246 int labelGotoGoto (iCode *ic)
251 for ( loop = ic ; loop ; loop = loop->next ) {
253 symbol *sLabel = NULL;
256 case GOTO: /* for a goto statement */
257 stat = hTabItemWithKey(labelDef,(sLabel = IC_LABEL(loop))->key) ;
259 case IFX : /* for a conditional jump */
261 stat = hTabItemWithKey(labelDef,(sLabel = IC_TRUE(loop))->key);
263 stat = hTabItemWithKey (labelDef,(sLabel = IC_FALSE(loop))->key);
266 /* if we have a target statement then check if the next */
267 /* one is a goto: this means target of goto is a goto */
268 if ( stat && stat->next &&
269 ( stat->next->op == GOTO ||
270 stat->next->op == LABEL) &&
271 stat->next != loop ) {
273 symbol *repLabel = stat->next->argLabel.label ; /* replace with label */
275 /* if they are the same then continue */
276 if (repLabel->key == sLabel->key)
279 /* replacement depends on the statement type */
282 case GOTO: /* for a goto statement */
284 hTabDeleteItem (&labelRef, (IC_LABEL(loop))->key, loop,DELETE_ITEM,NULL);
285 loop->argLabel.label = repLabel ;
286 hTabAddItem (&labelRef, repLabel->key, loop);
289 case IFX : /* for a conditional jump */
292 hTabDeleteItem (&labelRef, (IC_TRUE(loop))->key, loop,DELETE_ITEM,NULL);
293 IC_TRUE(loop) = repLabel ;
297 hTabDeleteItem (&labelRef, (IC_FALSE(loop))->key, loop,DELETE_ITEM,NULL);
298 IC_FALSE(loop) = repLabel;
300 hTabAddItem (&labelRef, repLabel->key, loop);
310 /*-----------------------------------------------------------------*/
311 /* labelUnrefLabel - remove unreferneced labels */
312 /*-----------------------------------------------------------------*/
313 int labelUnrefLabel (iCode *ic)
318 for ( loop = ic ; loop ; loop = loop->next) {
320 /* if this is a label */
321 if (loop->op == LABEL) {
325 if ( ( (IC_LABEL(loop))->key == returnLabel->key ) ||
326 ( (IC_LABEL(loop))->key == entryLabel->key ) )
329 if (hTabItemWithKey(labelRef,(IC_LABEL(loop))->key) )
332 /* else eliminitate this one */
333 loop->prev->next = loop->next ; /* get this out of the chain */
334 loop->next->prev = loop->prev ;
342 /*-----------------------------------------------------------------*/
343 /* labelUnreach - remove unreachable code */
344 /*-----------------------------------------------------------------*/
345 int labelUnreach (iCode *ic)
351 /* if we hit a return statement or a goto statement */
352 /* remove all statements till we hit the next label */
353 for (loop = ic ; loop ; loop = loop->next) {
356 /* found a goto || return && the next */
357 /* statement is not a label */
358 if (loop->op == GOTO || loop->op == RETURN ) {
361 (loop->next->op == LABEL ||
362 loop->next->op == ENDFUNCTION ))
365 /* loop till we find a label */
367 while (loop2 && loop2->op != LABEL)
370 /* throw away those in between */
371 for (tic = loop->next ; tic && tic != loop2 ; tic=tic->next) {
372 /* remove label references if any */
375 hTabDeleteItem (&labelRef,IC_LABEL(tic)->key,tic,DELETE_ITEM,NULL);
379 hTabDeleteItem (&labelRef,IC_TRUE(tic)->key,tic,DELETE_ITEM,NULL);
381 hTabDeleteItem (&labelRef,IC_FALSE(tic)->key,tic,DELETE_ITEM,NULL);
387 /* now set up the pointers */
397 /*-----------------------------------------------------------------*/
398 /* iCodeLabelOptimize - some obvious & general optimizations */
399 /*-----------------------------------------------------------------*/
400 iCode *iCodeLabelOptimize (iCode *ic)
402 if (!optimize.label1 &&
408 /* build labelreferences */
409 buildLabelRefTable (ic);
411 /* the following transformations need to ne done */
412 /* repeatedly till a fixed point is reached */
417 /* first eliminate any goto statement */
418 /* that goes to the next statement */
420 change += labelGotoNext (ic);
422 if ( optimize.label2 )
423 change += labelIfx (ic);
425 /* target of a goto is a goto then rename this goto */
426 if (optimize.label3 )
427 change += labelGotoGoto (ic);
429 /* remove unreference labels */
431 change += labelUnrefLabel (ic);
433 /* remove unreachable code */
434 change += labelUnreach (ic);
436 if (!change) /* fixed point reached */