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
)
105 werrorfl (loop
->filename
, loop
->lineno
, W_CONTROL_FLOW
);
106 hTabDeleteItem (&labelRef
, key
, loop
, DELETE_ITEM
, NULL
);
108 /* If the condition was volatile, convert IFX to */
109 /* DUMMY_READ_VOLATILE. Otherwise just delete the */
111 if (IS_OP_VOLATILE (IC_COND (loop
)))
113 IC_RIGHT (loop
) = IC_COND (loop
);
114 IC_LEFT (loop
) = NULL
;
115 IC_RESULT (loop
) = NULL
;
116 loop
->op
= DUMMY_READ_VOLATILE
;
120 loop
->prev
->next
= loop
->next
;
121 loop
->next
->prev
= loop
->prev
;
126 /*-----------------------------------------------------------------*/
127 /* labelIfx - special case Ifx elimination */
128 /*-----------------------------------------------------------------*/
130 labelIfx (iCode
* ic
)
136 for (loop
= ic
; loop
; loop
= loop
->next
)
138 /* if condition goto label */
140 /* i.e. the flow is going to the same location
141 regardless of the condition in this case the
142 condition can be eliminated with a WARNING of course */
143 if (loop
->op
== IFX
&&
145 loop
->next
->op
== GOTO
)
147 if (IC_TRUE (loop
) && IC_TRUE (loop
)->key
== IC_LABEL (loop
->next
)->key
)
149 deleteIfx (loop
, IC_TRUE (loop
)->key
);
155 if (IC_FALSE (loop
) && IC_FALSE (loop
)->key
== IC_LABEL (loop
->next
)->key
)
157 deleteIfx (loop
, IC_FALSE (loop
)->key
);
163 /* same as above but with a twist */
164 /* if condition goto label */
166 if (loop
->op
== IFX
&&
168 loop
->next
->op
== LABEL
&&
169 ((IC_TRUE (loop
) && IC_TRUE (loop
)->key
== IC_LABEL (loop
->next
)->key
) ||
170 (IC_FALSE (loop
) && IC_FALSE (loop
)->key
== IC_LABEL (loop
->next
)->key
)))
172 deleteIfx (loop
, IC_LABEL (loop
->next
)->key
);
177 /* we will eliminate certain special case situations */
178 /* of the conditional statement :- */
179 /* if cond != 0 goto _trueLabel */
180 /* goto _falseLabel */
183 /* in these cases we can change it to :- */
184 /* if cond == 0 goto _falseLabel */
187 /* similarly if we have a situation like :- */
188 /* if cond == 0 goto _falseLabel */
189 /* goto _someLabel */
191 /* we can change this to */
192 /* if cond != 0 goto _someLabel */
195 if (loop
->op
== IFX
&& loop
->next
&& loop
->next
->op
== GOTO
&&
196 loop
->next
->next
&& loop
->next
->next
->op
== LABEL
)
198 if (IC_TRUE (loop
) && (IC_TRUE (loop
))->key
!= (IC_LABEL (loop
->next
->next
))->key
||
199 (IC_FALSE (loop
) && (IC_FALSE (loop
))->key
!= (IC_LABEL (loop
->next
->next
))->key
))
202 /* now make sure that this is the only */
203 /* reference to the _trueLabel */
204 if (IC_TRUE (loop
) && hTabItemWithKey (labelRef
, (IC_TRUE (loop
))->key
))
206 /* we just change the falseLabel */
207 /* to the next goto statement */
208 /* unreferenced label will take */
209 /* care of removing the label */
210 /* delete reference to the true label */
212 hTabDeleteItem (&labelRef
, (IC_TRUE (loop
))->key
, loop
, DELETE_ITEM
, NULL
);
213 IC_TRUE (loop
) = NULL
;
214 IC_FALSE (loop
) = IC_LABEL (loop
->next
);
215 /* add reference to the LABEL */
216 hTabAddItem (&labelRef
, (IC_FALSE (loop
))->key
, loop
);
217 /* next remove the goto */
218 hTabDeleteItem (&labelRef
,
219 (IC_LABEL (loop
->next
))->key
, loop
->next
, DELETE_ITEM
, NULL
);
220 loop
->next
= loop
->next
->next
;
221 loop
->next
->prev
= loop
;
226 /* now do the same with the false labels */
227 if (IC_FALSE (loop
) && hTabItemWithKey (labelRef
, (IC_FALSE (loop
))->key
))
229 hTabDeleteItem (&labelRef
, (IC_FALSE (loop
))->key
, loop
, DELETE_ITEM
, NULL
);
230 IC_FALSE (loop
) = NULL
;
231 IC_TRUE (loop
) = IC_LABEL (loop
->next
);
232 hTabAddItem (&labelRef
, (IC_TRUE (loop
))->key
, loop
);
233 hTabDeleteItem (&labelRef
, (IC_LABEL (loop
->next
))->key
, loop
->next
, DELETE_ITEM
, NULL
);
234 loop
->next
= loop
->next
->next
;
235 loop
->next
->prev
= loop
;
241 /* Optimize hidden jump-to-jump:
248 if (v) goto l3; loop->next
255 if (loop
->op
== LABEL
&&
256 loop
->next
&& loop
->next
->op
== IFX
&&
257 (stat
= hTabFirstItemWK (labelRef
, (IC_LABEL (loop
))->key
)) &&
258 !hTabNextItemWK (labelRef
) &&
259 stat
&& stat
->op
== GOTO
&&
260 stat
->prev
&& stat
->prev
->op
== '=' && IS_OP_LITERAL (IC_RIGHT (stat
->prev
)) &&
261 loop
->prev
&& loop
->prev
->op
== '=' && IS_OP_LITERAL (IC_RIGHT (loop
->prev
)) &&
262 IC_RESULT (stat
->prev
)->key
== IC_COND (loop
->next
)->key
&&
263 IC_RESULT (loop
->prev
)->key
== IC_COND (loop
->next
)->key
&&
264 !IS_OP_VOLATILE (IC_COND (loop
->next
)) &&
265 (!operandLitValue (IC_RIGHT (stat
->prev
)) ^ !operandLitValue (IC_RIGHT (loop
->prev
))))
267 if (IC_FALSE (loop
->next
) && !operandLitValue (IC_RIGHT (loop
->prev
)) ||
268 IC_TRUE (loop
->next
) && operandLitValue (IC_RIGHT (loop
->prev
)))
269 /* Complicated case: Insert goto, remove conditional jump. */
271 /* Change IFX to GOTO. */
273 IC_LABEL (stat
) = IC_TRUE (stat
) ? IC_TRUE (stat
) : IC_FALSE (stat
);
276 /* Move to desired location. */
277 if (loop
->next
->next
)
278 loop
->next
->next
->prev
= loop
;
279 loop
->next
= loop
->next
->next
;
280 stat
->prev
= loop
->prev
;
281 stat
->prev
->next
= stat
;
287 else /* Simple case: Redirect goto, remove conditional jump. */
289 hTabDeleteItem (&labelRef
, (IC_LABEL (stat
))->key
, stat
, DELETE_ITEM
, NULL
);
290 IC_LABEL (stat
) = IC_TRUE (loop
->next
) ? IC_TRUE (loop
->next
) : IC_FALSE (loop
->next
);
291 hTabAddItem (&labelRef
, (IC_LABEL (stat
))->key
, stat
);
292 hTabDeleteItem (&labelRef
, IC_LABEL (stat
)->key
, loop
->next
, DELETE_ITEM
, NULL
);
293 if (loop
->next
->next
)
294 loop
->next
->next
->prev
= loop
;
295 loop
->next
= loop
->next
->next
;
305 /*-----------------------------------------------------------------*/
306 /* labelJumptable - eliminate or simplify jump tables */
307 /*-----------------------------------------------------------------*/
309 labelJumptable (iCode
* ic
)
314 for (loop
= ic
; loop
; loop
= loop
->next
)
316 /* Jump table with constant can be replace with GOTO */
317 if (loop
->op
== JUMPTABLE
&&
318 isOperandLiteral (IC_JTCOND (loop
)))
320 symbol
*lbl
, *caselbl
= NULL
;
321 int casenum
, constcasenum
;
323 constcasenum
= operandLitValue (IC_JTCOND (loop
));
325 werrorfl (loop
->filename
, loop
->lineno
, W_CONTROL_FLOW
);
327 /* Delete all the references except for the one that we keep */
328 for (casenum
= 0, lbl
= setFirstItem (IC_JTLABELS (loop
)); lbl
;
329 casenum
++, lbl
= setNextItem (IC_JTLABELS (loop
)))
331 if (constcasenum
== casenum
)
332 caselbl
= lbl
; /* keep this reference, remember this label */
334 hTabDeleteItem (&labelRef
, lbl
->key
, loop
, DELETE_ITEM
, NULL
);
338 loop
->label
= caselbl
;
339 IC_LEFT (loop
) = NULL
;
340 IC_RIGHT (loop
) = NULL
;
341 IC_RESULT (loop
) = NULL
;
350 /*-----------------------------------------------------------------*/
351 /* replaceGotoGoto - find new target for jump */
352 /* if we have a target statement then check if the next */
353 /* one is a goto: this means target of goto is a goto */
354 /*-----------------------------------------------------------------*/
356 replaceGotoGoto (const iCode
*ic
, const symbol
*sLabel
, const iCode
*target
)
358 if (!target
|| !target
->next
)
361 if (target
->next
->op
!= GOTO
&& target
->next
->op
!= LABEL
|| target
->next
== ic
)
364 symbol
*repLabel
= target
->next
->label
;
366 if (repLabel
== sLabel
)
373 /*-----------------------------------------------------------------*/
374 /* labelGotoGoto - target of a goto is a goto */
375 /*-----------------------------------------------------------------*/
377 labelGotoGoto (iCode
*ic
)
382 for (loop
= ic
; loop
; loop
= loop
->next
)
385 symbol
*sLabel
= NULL
;
390 case GOTO
: /* for a goto statement */
392 stat
= hTabItemWithKey (labelDef
, (sLabel
= IC_LABEL (loop
))->key
);
394 if (repLabel
= replaceGotoGoto (loop
, sLabel
, stat
))
396 hTabDeleteItem (&labelRef
, sLabel
->key
, loop
, DELETE_ITEM
, NULL
);
397 loop
->label
= repLabel
;
398 hTabAddItem (&labelRef
, repLabel
->key
, loop
);
403 case IFX
: /* for a conditional jump */
406 stat
= hTabItemWithKey (labelDef
, (sLabel
= IC_TRUE (loop
))->key
);
408 stat
= hTabItemWithKey (labelDef
, (sLabel
= IC_FALSE (loop
))->key
);
410 if (repLabel
= replaceGotoGoto (loop
, sLabel
, stat
))
414 hTabDeleteItem (&labelRef
, sLabel
->key
, loop
, DELETE_ITEM
, NULL
);
415 IC_TRUE (loop
) = repLabel
;
419 hTabDeleteItem (&labelRef
, sLabel
->key
, loop
, DELETE_ITEM
, NULL
);
420 IC_FALSE (loop
) = repLabel
;
422 hTabAddItem (&labelRef
, repLabel
->key
, loop
);
423 stat
->mergedElsewhere
= 1;
424 stat
->next
->mergedElsewhere
= 1;
431 for (sLabel
= setFirstItem (IC_JTLABELS (loop
)); sLabel
; sLabel
= setNextItem (IC_JTLABELS (loop
)))
433 stat
= hTabItemWithKey (labelDef
, sLabel
->key
);
434 if (repLabel
= replaceGotoGoto (loop
, sLabel
, stat
))
436 hTabDeleteItem (&labelRef
, sLabel
->key
, loop
, DELETE_ITEM
, NULL
);
437 replaceSetItem (IC_JTLABELS (loop
), sLabel
, repLabel
);
438 hTabAddItem (&labelRef
, repLabel
->key
, loop
);
439 stat
->mergedElsewhere
= 1;
440 stat
->next
->mergedElsewhere
= 1;
450 /*-----------------------------------------------------------------*/
451 /* labelUnrefLabel - remove unreferenced labels */
452 /*-----------------------------------------------------------------*/
454 labelUnrefLabel (iCode
* ic
)
459 for (loop
= ic
; loop
; loop
= loop
->next
)
462 /* if this is a label */
463 if (loop
->op
== LABEL
)
465 if (((IC_LABEL (loop
))->key
== returnLabel
->key
) ||
466 ((IC_LABEL (loop
))->key
== entryLabel
->key
))
469 if (hTabItemWithKey (labelRef
, (IC_LABEL (loop
))->key
))
472 /* else eliminate this one */
473 loop
->prev
->next
= loop
->next
; /* get this out of the chain */
474 loop
->next
->prev
= loop
->prev
;
482 /*-----------------------------------------------------------------*/
483 /* labelUnreach - remove unreachable code */
484 /*-----------------------------------------------------------------*/
486 labelUnreach (iCode
*ic
)
492 /* if we hit a return statement or a goto statement */
493 /* remove all statements till we hit the next label */
494 for (loop
= ic
; loop
; loop
= loop
->next
)
498 /* found a goto || return && the next */
499 /* statement is not a label */
500 if (loop
->op
== GOTO
|| loop
->op
== RETURN
||
501 loop
->op
== CALL
&& IFFUNC_ISNORETURN (operandType (IC_LEFT (loop
))))
504 (loop
->next
->op
== LABEL
|| loop
->next
->op
== ENDFUNCTION
))
507 /* loop till we find a label */
509 while (loop2
&& loop2
->op
!= LABEL
)
512 /* throw away those in between */
513 for (tic
= loop
->next
; tic
&& tic
!= loop2
; tic
= tic
->next
)
516 if (tic
->op
!= GOTO
&& !tic
->inlined
&& !tic
->mergedElsewhere
)
517 werrorfl (tic
->filename
, tic
->lineno
, W_CODE_UNREACH
);
518 /* remove label references if any */
522 hTabDeleteItem (&labelRef
, IC_LABEL (tic
)->key
, tic
, DELETE_ITEM
, NULL
);
526 hTabDeleteItem (&labelRef
, IC_TRUE (tic
)->key
, tic
, DELETE_ITEM
, NULL
);
528 hTabDeleteItem (&labelRef
, IC_FALSE (tic
)->key
, tic
, DELETE_ITEM
, NULL
);
529 if (IS_SYMOP (IC_COND (tic
)) && OP_USES (IC_COND (tic
)))
530 bitVectUnSetBit (OP_USES (IC_COND (tic
)), tic
->key
);
533 for (lbl
= setFirstItem (IC_JTLABELS (tic
)); lbl
;
534 lbl
= setNextItem (IC_JTLABELS (tic
)))
536 hTabDeleteItem (&labelRef
, lbl
->key
, tic
, DELETE_ITEM
, NULL
);
538 if (IS_SYMOP (IC_JTCOND (tic
)) && OP_USES (IC_JTCOND (tic
)))
539 bitVectUnSetBit (OP_USES (IC_JTCOND (tic
)), tic
->key
);
542 if (IS_SYMOP (tic
->left
))
544 if (OP_SYMBOL (tic
->left
)->isstrlit
)
545 freeStringSymbol (OP_SYMBOL (tic
->left
));
546 if (OP_USES (tic
->left
))
547 bitVectUnSetBit (OP_USES (tic
->left
), tic
->key
);
549 if (IS_SYMOP (tic
->right
))
551 if (OP_SYMBOL (tic
->right
)->isstrlit
)
552 freeStringSymbol (OP_SYMBOL (tic
->right
));
553 if (OP_USES (tic
->right
))
554 bitVectUnSetBit (OP_USES (tic
->right
), tic
->key
);
556 if (POINTER_SET (tic
))
558 if (IS_SYMOP (IC_RESULT (tic
)) && OP_USES (IC_RESULT (tic
)))
559 bitVectUnSetBit (OP_DEFS (IC_RESULT (tic
)), tic
->key
);
563 if (IS_SYMOP (IC_RESULT (tic
)) && OP_DEFS (IC_RESULT (tic
)))
564 bitVectUnSetBit (OP_DEFS (IC_RESULT (tic
)), tic
->key
);
569 /* now set up the pointers */
579 /*-----------------------------------------------------------------*/
580 /* iCodeLabelOptimize - some obvious & general optimizations */
581 /*-----------------------------------------------------------------*/
583 iCodeLabelOptimize (iCode
* ic
)
585 if (!optimize
.label1
&&
591 /* build labelreferences */
592 buildLabelRefTable (ic
);
594 /* the following transformations need to ne done */
595 /* repeatedly till a fixed point is reached */
601 /* first eliminate any goto statement */
602 /* that goes to the next statement */
604 change
+= labelGotoNext (ic
);
607 change
+= labelIfx (ic
);
609 change
+= labelJumptable (ic
);
611 /* target of a goto is a goto then rename this goto */
613 change
+= labelGotoGoto (ic
);
615 /* remove unreference labels */
617 change
+= labelUnrefLabel (ic
);
619 /* remove unreachable code */
620 change
+= labelUnreach (ic
);
622 if (!change
) /* fixed point reached */