1 /*-------------------------------------------------------------------------
2 SDCCcse.c - source file for Common Subexpressions and other utility
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 #include "SDCCglobl.h"
31 #include "SDCChasht.h"
34 #include "SDCCicode.h"
35 #include "SDCClabel.h"
36 #include "SDCCBBlock.h"
37 #include "SDCCcflow.h"
41 /*-----------------------------------------------------------------*/
42 /* newCseDef - new cseDef */
43 /*-----------------------------------------------------------------*/
44 cseDef *newCseDef (operand *sym, iCode *ic)
49 ALLOC(cdp,sizeof(cseDef));
60 /*-----------------------------------------------------------------*/
61 /* int isCseDefEqual - two definitions are equal */
62 /*-----------------------------------------------------------------*/
63 int isCseDefEqual ( void *vsrc, void *vdest)
71 return (src->key == dest->key &&
72 src->diCode == dest->diCode ) ;
76 /*-----------------------------------------------------------------*/
77 /* pcseDef - in the cseDef */
78 /*-----------------------------------------------------------------*/
79 int pcseDef (void *item, va_list ap)
85 fprintf(stdout,"**null op**");
86 printOperand(cdp->sym,stdout);
87 icTab = getTableEntry(cdp->diCode->op) ;
88 icTab->iCodePrint(stdout,cdp->diCode,icTab->printName);
92 /*-----------------------------------------------------------------*/
93 /* replaceAllSymBySym - replaces all operands by operand in an */
94 /* instruction chain */
95 /*-----------------------------------------------------------------*/
96 void replaceAllSymBySym (iCode *ic, operand *from , operand *to)
100 for (lic = ic ; lic ; lic = lic->next ) {
103 if (IC_RESULT(lic) && IC_RESULT(lic)->key == from->key ) {
104 /* maintain du chains */
105 if (POINTER_SET(lic)) {
106 bitVectUnSetBit (OP_USES(from),lic->key);
107 OP_USES(to) = bitVectSetBit (OP_USES(to),lic->key);
110 bitVectUnSetBit (OP_DEFS(from),lic->key);
111 OP_DEFS(to) = bitVectSetBit (OP_DEFS(to),lic->key);
113 siaddr = IC_RESULT(lic)->isaddr ;
114 IC_RESULT(lic) = operandFromOperand(to);
115 IC_RESULT(lic)->isaddr = siaddr ;
118 if (IC_RIGHT(lic) && IC_RIGHT(lic)->key == from->key ) {
119 bitVectUnSetBit (OP_USES(from),lic->key);
120 OP_USES(to) = bitVectSetBit(OP_USES(to),lic->key);
121 siaddr = IC_RIGHT(lic)->isaddr ;
122 IC_RIGHT(lic) = operandFromOperand(to);
123 IC_RIGHT(lic)->isaddr = siaddr ;
126 if (IC_LEFT(lic) && IC_LEFT(lic)->key == from->key ) {
127 bitVectUnSetBit (OP_USES(from),lic->key);
128 OP_USES(to) = bitVectSetBit(OP_USES(to),lic->key);
129 siaddr = IC_LEFT(lic)->isaddr ;
130 IC_LEFT(lic) = operandFromOperand(to);
131 IC_LEFT(lic)->isaddr = siaddr ;
136 /*-----------------------------------------------------------------*/
137 /* iCodeKeyIs - if the icode keys match then return 1 */
138 /*-----------------------------------------------------------------*/
139 DEFSETFUNC(iCodeKeyIs)
144 if (cdp->diCode->key == key)
150 /*-----------------------------------------------------------------*/
151 /* removeFromInExprs - removes an icode from inexpressions */
152 /*-----------------------------------------------------------------*/
153 DEFSETFUNC(removeFromInExprs)
157 V_ARG(operand *,from);
159 V_ARG(eBBlock *,cbp);
165 deleteItemIf(&ebp->inExprs,iCodeKeyIs,ic->key);
166 if (ebp != cbp && !bitVectBitValue(cbp->domVect,ebp->bbnum))
167 replaceAllSymBySym(ebp->sch,from,to);
169 applyToSet(ebp->succList,removeFromInExprs,ic,from,to,cbp);
173 /*-----------------------------------------------------------------*/
174 /* isGlobalInNearSpace - return TRUE if valriable is a globalin data */
175 /*-----------------------------------------------------------------*/
176 static bool isGlobalInNearSpace (operand *op)
178 link *type = getSpec(operandType(op));
179 /* this is 8051 specific: optimization
180 suggested by Jean-Louis VERN, with 8051s we have no
181 advantage of putting variables in near space into
183 if (isOperandGlobal(op) &&
184 IN_DIRSPACE(SPEC_OCLS(type)))
190 /*-----------------------------------------------------------------*/
191 /* findCheaperOp - cseBBlock support routine, will check to see if */
192 /* we have a operand previously defined */
193 /*-----------------------------------------------------------------*/
194 DEFSETFUNC(findCheaperOp)
197 V_ARG(operand *,cop);
198 V_ARG(operand **,opp);
200 /* if we have already found it */
204 /* not found it yet check if this is the one */
205 /* and this is not the defining one */
206 if (cop->key == cdp->key) {
208 /* do a special check this will help in */
209 /* constant propagation & dead code elim*/
210 /* for assignments only */
211 if (cdp->diCode->op == '=') {
212 /* if the result is volatile then return result */
213 if (IS_OP_VOLATILE (IC_RESULT(cdp->diCode)))
214 *opp = IC_RESULT(cdp->diCode);
216 /* if this is a straight assignment and
217 left is a temp then prefer the temporary to the
219 if (!POINTER_SET(cdp->diCode) &&
220 IS_ITEMP(IC_RESULT(cdp->diCode)) &&
221 IS_TRUE_SYMOP(IC_RIGHT(cdp->diCode)))
222 *opp = IC_RESULT(cdp->diCode);
224 /* if straight assignement && and both
225 are temps then prefer the one that
226 will not need extra space to spil, also
227 take into consideration if right side
228 an induction variable
230 if (!POINTER_SET(cdp->diCode) &&
231 IS_ITEMP(IC_RESULT(cdp->diCode)) &&
232 IS_ITEMP(IC_RIGHT(cdp->diCode)) &&
233 !OP_SYMBOL(IC_RIGHT(cdp->diCode))->isind &&
234 ( (!SPIL_LOC(IC_RIGHT(cdp->diCode)) &&
235 SPIL_LOC(IC_RESULT(cdp->diCode))) ||
236 ( SPIL_LOC(IC_RESULT(cdp->diCode)) &&
237 SPIL_LOC(IC_RESULT(cdp->diCode)) ==
238 SPIL_LOC(IC_RIGHT(cdp->diCode))) )
240 *opp = IC_RESULT(cdp->diCode);
242 *opp = IC_RIGHT(cdp->diCode);
245 *opp = IC_RESULT(cdp->diCode) ;
248 /* if this is an assign to a temp. then check
249 if the right side is this then return this */
250 if (IS_TRUE_SYMOP(cop) &&
251 cdp->diCode->op == '=' &&
252 !POINTER_SET(cdp->diCode) &&
253 cop->key == IC_RIGHT(cdp->diCode)->key &&
254 !isGlobalInNearSpace (IC_RIGHT(cdp->diCode)) &&
255 IS_ITEMP(IC_RESULT(cdp->diCode)))
256 *opp = IC_RESULT(cdp->diCode);
260 if ((isGlobalInNearSpace(cop) &&
261 !isOperandLiteral(*opp)) ||
262 isOperandVolatile(*opp,FALSE)
268 if (cop->key == (*opp)->key ) {
273 if ((*opp)->isaddr != cop->isaddr && IS_ITEMP(cop)) {
274 *opp = operandFromOperand(*opp);
275 (*opp)->isaddr = cop->isaddr;
285 /*-----------------------------------------------------------------*/
286 /* findPointerSet - finds the right side of a pointer set op */
287 /*-----------------------------------------------------------------*/
288 DEFSETFUNC(findPointerSet)
292 V_ARG(operand **,opp);
294 if (POINTER_SET(cdp->diCode) &&
295 IC_RESULT(cdp->diCode)->key == op->key &&
296 !isOperandVolatile(IC_RESULT(cdp->diCode),TRUE) &&
297 !isOperandVolatile(IC_RIGHT(cdp->diCode),TRUE)) {
298 *opp = IC_RIGHT(cdp->diCode);
305 /*-----------------------------------------------------------------*/
306 /* findPrevIc - cseBBlock support function will return the iCode */
307 /* which matches the current one */
308 /*-----------------------------------------------------------------*/
309 DEFSETFUNC(findPrevIc)
315 /* if already found */
319 /* if the iCodes are the same */
320 if (isiCodeEqual(ic,cdp->diCode) &&
321 isOperandEqual(cdp->sym,IC_RESULT(cdp->diCode))) {
326 /* if iCodes are not the same */
327 /* see the operands maybe interchanged */
328 if (ic->op == cdp->diCode->op &&
329 ( ic->op == '+' || ic->op == '*' ) &&
330 isOperandEqual(IC_LEFT(ic),IC_RIGHT(cdp->diCode)) &&
331 isOperandEqual(IC_RIGHT(ic),IC_LEFT(cdp->diCode))) {
339 /*-----------------------------------------------------------------*/
340 /* ifDefGlobal - if definition is global */
341 /*-----------------------------------------------------------------*/
342 DEFSETFUNC(ifDefGlobal)
346 return (isOperandGlobal(cdp->sym));
349 /*-----------------------------------------------------------------*/
350 /* ifOperandsHave - if any of the operand are the same as this */
351 /*-----------------------------------------------------------------*/
352 DEFSETFUNC(ifOperandsHave)
358 if (IC_LEFT(cdp->diCode) &&
359 IS_SYMOP(IC_LEFT(cdp->diCode)) &&
360 IC_LEFT(cdp->diCode)->key == op->key)
363 if (IC_RIGHT(cdp->diCode) &&
364 IS_SYMOP(IC_RIGHT(cdp->diCode)) &&
365 IC_RIGHT(cdp->diCode)->key == op->key)
368 /* or if any of the operands are volatile */
369 if (IC_LEFT(cdp->diCode) &&
370 IS_OP_VOLATILE(IC_LEFT(cdp->diCode)))
373 if (IC_RIGHT(cdp->diCode) &&
374 IS_OP_VOLATILE(IC_RIGHT(cdp->diCode)))
378 if (IC_RESULT(cdp->diCode) &&
379 IS_OP_VOLATILE(IC_RESULT(cdp->diCode)))
385 /*-----------------------------------------------------------------*/
386 /* ifDefSymIs - if a definition is found in the set */
387 /*-----------------------------------------------------------------*/
388 int ifDefSymIs (set *cseSet, operand *sym)
393 if (!sym || !IS_SYMOP(sym))
395 for (sl = cseSet ; sl ; sl = sl->next ) {
397 if (loop->sym->key == sym->key )
404 /*-----------------------------------------------------------------*/
405 /* ifDefSymIsX - will return 1 if the symbols match */
406 /*-----------------------------------------------------------------*/
407 DEFSETFUNC(ifDefSymIsX)
413 return cdp->sym->key == op->key ;
415 return ( isOperandEqual(cdp->sym,op) );
420 /*-----------------------------------------------------------------*/
421 /* ifDiCodeIs - returns truw if diCode is same */
422 /*-----------------------------------------------------------------*/
423 int ifDiCodeIs (set *cseSet, iCode *ic)
431 for (sl = cseSet ; sl ; sl = sl->next ) {
433 if (loop->diCode == ic)
440 /*-----------------------------------------------------------------*/
441 /* ifPointerGet - returns true if the icode is pointer get sym */
442 /*-----------------------------------------------------------------*/
443 DEFSETFUNC(ifPointerGet)
448 if (POINTER_GET(cdp->diCode) &&
449 IC_LEFT(cdp->diCode)->key == op->key)
455 /*-----------------------------------------------------------------*/
456 /* ifPointerSet - returns true if the icode is pointer set sym */
457 /*-----------------------------------------------------------------*/
458 DEFSETFUNC(ifPointerSet)
463 if (POINTER_SET(cdp->diCode) &&
464 IC_RESULT(cdp->diCode)->key == op->key)
470 /*-----------------------------------------------------------------*/
471 /* ifDiCodeIsX - will return 1 if the symbols match */
472 /*-----------------------------------------------------------------*/
473 DEFSETFUNC(ifDiCodeIsX)
478 return cdp->diCode == ic;
482 /*-----------------------------------------------------------------*/
483 /* algebraicOpts - does some algebraic optimizations */
484 /*-----------------------------------------------------------------*/
485 void algebraicOpts (iCode *ic)
487 /* we don't deal with the following iCodes
498 /* if both operands present & ! IFX */
499 /* then if they are both literal we */
500 /* perform the operation right now */
504 IS_OP_LITERAL(IC_LEFT(ic)) &&
505 IS_OP_LITERAL(IC_RIGHT(ic))) {
507 IC_RIGHT(ic) = operandOperation (IC_LEFT(ic),
510 operandType(IC_RESULT(ic)));
513 SET_RESULT_RIGHT(ic);
517 /* if not ifx & only one operand present */
520 IS_OP_LITERAL(IC_LEFT(ic)) &&
523 IC_RIGHT(ic) = operandOperation (IC_LEFT(ic),
526 operandType(IC_RESULT(ic)));
529 SET_RESULT_RIGHT(ic);
534 /* a special case : or in short a kludgy solution will think
535 about a better solution over a glass of wine someday */
536 if ( ic->op == GET_VALUE_AT_ADDRESS ) {
538 if (IS_ITEMP(IC_RESULT(ic)) &&
539 IS_TRUE_SYMOP(IC_LEFT(ic))) {
542 IC_RIGHT(ic) = operandFromOperand(IC_LEFT(ic));
543 IC_RIGHT(ic)->isaddr = 0;
545 IC_RESULT(ic) = operandFromOperand(IC_RESULT(ic));
546 IC_RESULT(ic)->isaddr = 0;
547 setOperandType(IC_RESULT(ic),operandType(IC_RIGHT(ic)));
551 if (IS_ITEMP(IC_LEFT(ic)) &&
552 IS_ITEMP(IC_RESULT(ic)) &&
553 /* !OP_SYMBOL(IC_RESULT(ic))->isreqv && */
554 /* !OP_SYMBOL(IC_LEFT(ic))->isreqv && */
555 !IC_LEFT(ic)->isaddr ) {
557 IC_RIGHT(ic) = operandFromOperand(IC_LEFT(ic));
558 IC_RIGHT(ic)->isaddr = 0;
559 IC_RESULT(ic) = operandFromOperand(IC_RESULT(ic));
560 IC_RESULT(ic)->isaddr = 0;
568 /* depending on the operation */
571 /* if adding the same thing change to left shift by 1*/
572 if (IC_LEFT(ic)->key == IC_RIGHT(ic)->key &&
573 !IS_FLOAT(operandType(IC_RESULT(ic)))) {
575 IC_RIGHT(ic) = operandFromLit(1);
578 /* if addition then check if one of them is a zero */
579 /* if yes turn it into assignmnt*/
580 if (IS_OP_LITERAL(IC_LEFT(ic)) &&
581 operandLitValue(IC_LEFT(ic)) == 0.0 ) {
585 SET_ISADDR(IC_RESULT(ic),0);
586 SET_ISADDR(IC_RIGHT(ic),0);
589 if (IS_OP_LITERAL(IC_RIGHT(ic)) &&
590 operandLitValue(IC_RIGHT(ic)) == 0.0 ) {
593 IC_RIGHT(ic) = IC_LEFT(ic) ;
595 SET_ISADDR(IC_RIGHT(ic),0);
596 SET_ISADDR(IC_RESULT(ic),0);
601 /* if subtracting the the same thing then zero */
602 if ( IC_LEFT(ic)->key == IC_RIGHT(ic)->key ) {
604 IC_RIGHT(ic) = operandFromLit(0);
606 IC_RESULT(ic) = operandFromOperand(IC_RESULT(ic));
607 IC_RESULT(ic)->isaddr = 0;
611 /* if subtraction then check if one of the operand */
612 /* is zero then depending on which operand change */
613 /* to assignment or unary minus */
614 if (IS_OP_LITERAL(IC_RIGHT(ic)) &&
615 operandLitValue(IC_RIGHT(ic)) == 0.0 ) {
616 /* right size zero change to assignment */
618 IC_RIGHT(ic) = IC_LEFT(ic);
620 SET_ISADDR(IC_RIGHT(ic),0);
621 SET_ISADDR(IC_RESULT(ic),0);
624 if (IS_OP_LITERAL(IC_LEFT(ic)) &&
625 operandLitValue (IC_LEFT(ic)) == 0.0) {
626 /* left zero turn into an unary minus */
627 ic->op = UNARYMINUS ;
628 IC_LEFT(ic) = IC_RIGHT(ic);
629 IC_RIGHT(ic) = NULL ;
633 /* if multiplication then check if either of */
634 /* them is zero then the result is zero */
635 /* if either of them is one then result is */
638 if (IS_OP_LITERAL(IC_LEFT(ic))) {
640 if (operandLitValue(IC_LEFT(ic)) == 0.0) {
642 IC_RIGHT(ic) = IC_LEFT(ic);
644 SET_RESULT_RIGHT(ic);
647 if ( operandLitValue(IC_LEFT(ic)) == 1.0) {
650 SET_RESULT_RIGHT(ic);
655 if (IS_OP_LITERAL(IC_RIGHT(ic))) {
657 if (operandLitValue(IC_RIGHT(ic)) == 0.0 ) {
660 SET_RESULT_RIGHT(ic);
664 if (operandLitValue(IC_RIGHT(ic)) == 1.0) {
666 IC_RIGHT(ic) = IC_LEFT(ic);
668 SET_RESULT_RIGHT(ic);
674 /* if division by self then 1 */
675 if (IC_LEFT(ic)->key == IC_RIGHT(ic)->key) {
677 IC_RIGHT(ic) = operandFromLit(1);
679 IC_RESULT(ic) = operandFromOperand(IC_RESULT(ic));
680 IC_RESULT(ic)->isaddr = 0;
682 /* if this is a division then check if right */
683 /* is one then change it to an assignment */
684 if (IS_OP_LITERAL(IC_RIGHT(ic)) &&
685 operandLitValue(IC_RIGHT(ic)) == 1.0 ) {
688 IC_RIGHT(ic) = IC_LEFT(ic);
690 SET_RESULT_RIGHT(ic);
694 /* if both are the same for an comparison operators */
698 if (isOperandEqual(IC_LEFT(ic),IC_RIGHT(ic))) {
700 IC_RIGHT(ic) = operandFromLit(1);
702 SET_RESULT_RIGHT(ic);
708 if (isOperandEqual(IC_LEFT(ic),IC_RIGHT(ic))) {
710 IC_RIGHT(ic) = operandFromLit(0);
712 SET_RESULT_RIGHT(ic);
716 /* if this is a cast of a literal value */
717 if ( IS_OP_LITERAL(IC_RIGHT(ic))) {
720 operandFromValue (valCastLiteral(operandType(IC_LEFT(ic)),
721 operandLitValue(IC_RIGHT(ic))));
723 SET_ISADDR(IC_RESULT(ic),0);
725 /* if casting to the same */
726 if ( checkType(operandType(IC_RESULT(ic)),
727 operandType(IC_RIGHT(ic))) == 1) {
730 SET_ISADDR(IC_RESULT(ic),0);
734 if (IS_OP_LITERAL(IC_LEFT(ic))) {
737 (operandLitValue(IC_LEFT(ic)) == 0 ?
738 operandFromLit(1) : operandFromLit(0));
740 SET_ISADDR(IC_RESULT(ic),0);
746 #define OTHERS_PARM(s) (s->_isparm && !s->ismyparm)
747 /*-----------------------------------------------------------------*/
748 /* updateSpillLocation - keeps track of register spill location */
749 /*-----------------------------------------------------------------*/
750 void updateSpillLocation ( iCode *ic)
761 /* for the form true_symbol := iTempNN */
762 if (ASSIGN_ITEMP_TO_SYM(ic)
763 && !SPIL_LOC(IC_RIGHT(ic))) {
765 setype = getSpec(operandType(IC_RESULT(ic)));
767 if (!IC_RIGHT(ic)->noSpilLoc &&
768 !IS_VOLATILE(setype) &&
769 !IN_FARSPACE(SPEC_OCLS(setype)) &&
770 !OTHERS_PARM(OP_SYMBOL(IC_RESULT(ic))) )
772 SPIL_LOC(IC_RIGHT(ic)) =
773 IC_RESULT(ic)->operand.symOperand;
776 if (ASSIGN_ITEMP_TO_ITEMP(ic) &&
777 !SPIL_LOC(IC_RIGHT(ic)) &&
778 OP_SYMBOL(IC_RESULT(ic))->isreqv) {
780 setype = getSpec(operandType(IC_RESULT(ic)));
782 if (!IC_RIGHT(ic)->noSpilLoc &&
783 !IS_VOLATILE(setype) &&
784 !IN_FARSPACE(SPEC_OCLS(setype)) &&
785 !OTHERS_PARM(OP_SYMBOL(IC_RESULT(ic))) )
787 SPIL_LOC(IC_RIGHT(ic)) =
788 SPIL_LOC(IC_RESULT(ic));
792 /*-----------------------------------------------------------------*/
793 /* setUsesDef - sets the uses def bitvector for a given operand */
794 /*-----------------------------------------------------------------*/
795 void setUsesDefs (operand *op, bitVect *bdefs,
796 bitVect *idefs, bitVect **oud)
798 /* compute the definitions alive at this point */
799 bitVect *adefs = bitVectUnion(bdefs,idefs);
801 /* of these definitions find the ones that are */
802 /* for this operand */
803 adefs = bitVectIntersect(adefs,OP_DEFS(op));
805 /* these are the definitions that this operand can use */
806 op->usesDefs = adefs;
808 /* the out defs is an union */
809 *oud = bitVectUnion(*oud,adefs);
812 /*-----------------------------------------------------------------*/
813 /* ifxOptimize - changes ifx conditions if it can */
814 /*-----------------------------------------------------------------*/
815 void ifxOptimize (iCode *ic, set *cseSet,
817 eBBlock *ebb, int *change,
818 eBBlock **ebbs, int count)
823 /* if the condition can be replaced */
826 applyToSetFTrue (cseSet,findCheaperOp,IC_COND(ic),&pdop);
833 /* if the conditional is a literal then */
834 if (IS_OP_LITERAL(IC_COND(ic))) {
836 if ( operandLitValue(IC_COND(ic)) && IC_TRUE(ic)) {
838 /* change to a goto */
840 IC_LABEL(ic) = IC_TRUE(ic);
845 if (!operandLitValue(IC_COND(ic)) && IC_FALSE(ic)) {
847 IC_LABEL(ic) = IC_FALSE(ic);
851 /* then kill this if condition */
852 remiCodeFromeBBlock (ebb,ic);
856 /* now we need to recompute the control flow */
857 /* since the control flow has changed */
858 /* this is very expensive but it does not happen */
859 /* too often, if it does happen then the user pays */
861 computeControlFlow (ebbs,count,1);
862 werror (W_CONTROL_FLOW,ic->filename,ic->lineno);
866 /* if there is only one successor and that successor
867 is the same one we are conditionally going to then
868 we can remove this conditional statement */
869 label = (IC_TRUE(ic) ? IC_TRUE(ic) : IC_FALSE(ic));
870 if (elementsInSet(ebb->succList) == 1 &&
871 isinSet(ebb->succList,eBBWithEntryLabel(ebbs,label,count))) {
873 remiCodeFromeBBlock(ebb,ic);
874 computeControlFlow (ebbs,count,1);
875 werror (W_CONTROL_FLOW,ic->filename,ic->lineno);
880 /* if it remains an IFX the update the use Set */
881 OP_USES(IC_COND(ic)) = bitVectSetBit(OP_USES(IC_COND(ic)),ic->key);
882 setUsesDefs(IC_COND(ic),ebb->defSet,ebb->outDefs,&ebb->usesDefs);
886 /*-----------------------------------------------------------------*/
887 /* unsetDefsAndUses - clear this operation for the operands */
888 /*-----------------------------------------------------------------*/
889 void unsetDefsAndUses ( iCode *ic )
891 if ( ic->op == JUMPTABLE)
894 /* take away this definition from the def chain of the */
895 /* result & take away from use set of the operands */
897 /* turn off def set */
898 if (IS_SYMOP(IC_RESULT(ic))) {
899 if ( !POINTER_SET(ic))
900 bitVectUnSetBit(OP_DEFS(IC_RESULT(ic)),ic->key);
902 bitVectUnSetBit(OP_USES(IC_RESULT(ic)),ic->key);
904 /* turn off the useSet for the operands */
905 if (IS_SYMOP(IC_LEFT(ic)))
906 bitVectUnSetBit (OP_USES(IC_LEFT(ic)),ic->key);
908 if (IS_SYMOP(IC_RIGHT(ic)))
909 bitVectUnSetBit (OP_USES(IC_RIGHT(ic)),ic->key);
911 else /* must be ifx turn off the use */
912 if (IS_SYMOP(IC_COND(ic)))
913 bitVectUnSetBit (OP_USES(IC_COND(ic)),ic->key);
916 /*-----------------------------------------------------------------*/
917 /* diCodeForSym - finds the definiting instruction for a symbol */
918 /*-----------------------------------------------------------------*/
919 DEFSETFUNC(diCodeForSym)
922 V_ARG(operand *,sym);
925 /* if already found */
929 /* if not if this is the defining iCode */
930 if (sym->key == cdp->key) {
938 /*-----------------------------------------------------------------*/
939 /* constFold - does some constant folding */
940 /*-----------------------------------------------------------------*/
941 int constFold (iCode *ic, set *cseSet)
944 /* this routine will change
950 /* deal with only + & - */
955 /* this check is a hueristic to prevent live ranges
956 from becoming too long */
957 if (IS_PTR(operandType(IC_RESULT(ic))))
960 /* check if operation with a literal */
961 if (!IS_OP_LITERAL(IC_RIGHT(ic)))
964 /* check if we can find a definition for the
966 if (!(applyToSet(cseSet,diCodeForSym,IC_LEFT(ic),&dic)))
969 /* check that this is also a +/- */
970 if (dic->op != '+' && dic->op != '-')
974 if (!IS_OP_LITERAL(IC_RIGHT(dic)))
977 /* it is if the operations are the same*/
978 /* the literal parts need to be added */
979 IC_LEFT(ic) = operandFromOperand(IC_LEFT(dic));
980 if (ic->op == dic->op )
981 IC_RIGHT(ic) = operandFromLit(operandLitValue(IC_RIGHT(ic))+
982 operandLitValue(IC_RIGHT(dic)));
984 IC_RIGHT(ic) = operandFromLit(operandLitValue(IC_RIGHT(ic)) -
985 operandLitValue(IC_RIGHT(dic)));
987 if (IS_ITEMP(IC_RESULT(ic))) {
988 SPIL_LOC(IC_RESULT(ic)) = NULL;
989 IC_RESULT(ic)->noSpilLoc = 1;
996 /*-----------------------------------------------------------------*/
997 /* deleteGetPointers - called when a pointer is passed as parm */
998 /* will delete from cseSet all get pointers computed from this */
999 /* pointer. A simple ifOperandsHave is not good enough here */
1000 /*-----------------------------------------------------------------*/
1001 static void deleteGetPointers (set **cseSet,operand *op,eBBlock *ebb)
1003 set *compItems = NULL;
1011 /* first find all items computed from this operand .
1012 This done fairly simply go thru the list and find
1013 those that are computed by arthimetic with this
1015 for (cdp = setFirstItem(*cseSet); cdp ; cdp = setNextItem(*cseSet)) {
1016 if (IS_ARITHMETIC_OP(cdp->diCode)) {
1017 if (isOperandEqual(IC_LEFT(cdp->diCode),op) ||
1018 isOperandEqual(IC_RIGHT(cdp->diCode),op)) {
1019 /* save it in our list of items */
1020 addSet(&compItems,IC_RESULT(cdp->diCode));
1022 /* also check for those computed from our computed
1023 list . This will take care of situations like
1024 iTemp1 = iTemp0 + 8;
1025 iTemp2 = iTemp1 + 8; */
1026 if (isinSetWith(compItems,IC_LEFT(cdp->diCode),isOperandEqual) ||
1027 isinSetWith(compItems,IC_RIGHT(cdp->diCode),isOperandEqual)) {
1028 addSet(&compItems,IC_RESULT(cdp->diCode));
1033 /* now delete all pointer gets with this op */
1034 deleteItemIf(cseSet,ifPointerGet,op);
1035 /* set the bit vector used by dataFlow computation later */
1036 ebb->ptrsSet = bitVectSetBit(ebb->ptrsSet,op->key);
1037 /* now for the computed items */
1038 for (cop = setFirstItem(compItems); cop ; cop = setNextItem(compItems)) {
1039 ebb->ptrsSet = bitVectSetBit(ebb->ptrsSet,cop->key);
1040 deleteItemIf(cseSet,ifPointerGet,cop);
1044 /*-----------------------------------------------------------------*/
1045 /* delGetPointerSucc - delete get pointer from inExprs of succ with*/
1046 /* dfnum > supplied */
1047 /*-----------------------------------------------------------------*/
1048 DEFSETFUNC(delGetPointerSucc)
1050 eBBlock *ebp = item;
1051 V_ARG(operand *,op);
1058 if (ebp->dfnum > dfnum) {
1059 deleteItemIf(&ebp->inExprs,ifPointerGet,op);
1062 return applyToSet(ebp->succList,delGetPointerSucc,op,dfnum);
1065 /*-----------------------------------------------------------------*/
1066 /* cseBBlock - common subexpression elimination for basic blocks */
1067 /* this is the hackiest kludgiest routine in the whole */
1068 /* system. also the most important, since almost all */
1069 /* data flow related information is computed by it */
1070 /*-----------------------------------------------------------------*/
1071 int cseBBlock ( eBBlock *ebb, int computeOnly,
1072 eBBlock **ebbs, int count)
1078 set *ptrSetSet = NULL;
1080 /* if this block is not reachable */
1084 /* set of common subexpressions */
1085 cseSet = setFromSet (ebb->inExprs) ;
1087 /* these will be computed by this routine */
1088 setToNull ((void **)&ebb->outDefs);
1089 setToNull ((void **)&ebb->defSet);
1090 setToNull ((void **)&ebb->usesDefs);
1091 setToNull ((void **)&ebb->ptrsSet);
1092 setToNull ((void **)&ebb->addrOf);
1093 setToNull ((void **)&ebb->ldefs);
1095 ebb->outDefs = bitVectCopy (ebb->inDefs);
1096 bitVectDefault = iCodeKey;
1097 ebb->defSet = newBitVect(iCodeKey);
1098 ebb->usesDefs=newBitVect(iCodeKey);
1100 /* for all the instructions in this block do */
1101 for (ic = ebb->sch ; ic ; ic = ic->next ) {
1110 /* clear the def & use chains for the operands involved */
1111 /* in this operation . since it can change due to opts */
1112 unsetDefsAndUses (ic);
1114 if ( ic->op == PCALL || ic->op == CALL || ic->op == RECEIVE) {
1115 /* add to defSet of the symbol */
1116 OP_DEFS(IC_RESULT(ic)) =
1117 bitVectSetBit (OP_DEFS(IC_RESULT(ic)),ic->key);
1118 /* add to the definition set of this block */
1119 ebb->defSet = bitVectSetBit (ebb->defSet,ic->key);
1120 ebb->ldefs = bitVectSetBit (ebb->ldefs,ic->key);
1121 ebb->outDefs= bitVectCplAnd (ebb->outDefs,OP_DEFS(IC_RESULT(ic)));
1122 setUsesDefs(IC_RESULT(ic),ebb->defSet,ebb->outDefs,&ebb->usesDefs);
1123 /* delete global variables from the cseSet
1124 since they can be modified by the function call */
1125 deleteItemIf(&cseSet,ifDefGlobal);
1128 /* for pcall & ipush we need to add to the useSet */
1129 if ((ic->op == PCALL ||
1133 IS_SYMOP(IC_LEFT(ic))) {
1135 /* check if they can be replaced */
1136 if ( !computeOnly ) {
1138 applyToSetFTrue(cseSet,findCheaperOp,IC_LEFT(ic),&pdop);
1140 IC_LEFT(ic) = pdop ;
1142 /* the lookup could have changed it*/
1143 if (IS_SYMOP(IC_LEFT(ic))) {
1144 OP_USES(IC_LEFT(ic)) =
1145 bitVectSetBit(OP_USES(IC_LEFT(ic)),ic->key);
1146 setUsesDefs(IC_LEFT(ic),ebb->defSet,
1147 ebb->outDefs,&ebb->usesDefs);
1149 /* if we a sending a pointer as a parameter
1150 then kill all cse since the pointed to item
1151 might be changed in the function being called */
1152 if (IS_PTR(operandType(IC_LEFT(ic)))) {
1153 deleteGetPointers(&cseSet,IC_LEFT(ic),ebb);
1158 /* if jumptable then mark the usage */
1159 if (ic->op == JUMPTABLE ) {
1160 OP_USES(IC_JTCOND(ic)) =
1161 bitVectSetBit(OP_USES(IC_JTCOND(ic)),ic->key);
1162 setUsesDefs(IC_JTCOND(ic),ebb->defSet,
1163 ebb->outDefs,&ebb->usesDefs);
1170 /* do some algebraic optimizations if possible */
1172 while (constFold(ic,cseSet));
1174 /* if this is a condition statment then */
1175 /* check if the condition can be replaced */
1176 if (ic->op == IFX ) {
1177 ifxOptimize (ic, cseSet, computeOnly,
1183 /* if the assignment & result is a temp */
1184 /* see if we can replace it */
1185 if (ic->op == '=') {
1187 /* update the spill location for this */
1188 updateSpillLocation (ic);
1190 if (POINTER_SET(ic)) {
1192 applyToSetFTrue (cseSet,findCheaperOp,IC_RESULT(ic),&pdop);
1193 if (pdop && IS_ITEMP(pdop) && !computeOnly)
1194 IC_RESULT(ic) = pdop;
1198 /* do the operand lookup i.e. for both the */
1199 /* right & left operand : check the cseSet */
1200 /* to see if they have been replaced if yes*/
1201 /* then replace them with those from cseSet*/
1203 /* and left is a symbol */
1204 if (IS_SYMOP(IC_LEFT(ic)) &&
1205 !computeOnly && ic->op != ADDRESS_OF ) {
1208 applyToSetFTrue (cseSet,findCheaperOp,IC_LEFT(ic),&pdop) ;
1210 if (POINTER_GET(ic)) {
1211 if (IS_ITEMP(pdop) || IS_OP_LITERAL(pdop)) {
1215 /* check if there is a pointer set
1216 for the same pointer visible if yes
1217 then change this into an assignment */
1219 if (applyToSetFTrue(cseSet,findPointerSet,IC_LEFT(ic),&pdop)){
1222 IC_RIGHT(ic) = pdop;
1223 SET_ISADDR(IC_RESULT(ic),0);
1228 IC_LEFT(ic) = pdop ;
1235 if (IS_SYMOP(IC_RIGHT(ic)) && !computeOnly) {
1238 applyToSetFTrue (cseSet,findCheaperOp,IC_RIGHT(ic),&pdop);
1241 IC_RIGHT(ic) = pdop;
1246 /* if left or right changed then do algebraic */
1249 while(constFold(ic,cseSet));
1252 /* if after all this it becomes a assignment to self
1253 then delete it and continue */
1254 if (ASSIGNMENT_TO_SELF(ic)) {
1255 remiCodeFromeBBlock(ebb,ic);
1259 /* now we will check to see if the entire */
1260 /* operation has been performed before */
1261 /* and is available */
1262 /* don't do assignments they will be killed */
1263 /* by dead code elimination if required do */
1264 /* it only if result is a temporary */
1266 if (!( POINTER_GET(ic) &&
1267 (IS_BITFIELD(OP_SYMBOL(IC_RESULT(ic))->etype) ||
1268 isOperandVolatile(IC_LEFT(ic),TRUE))) &&
1270 IS_ITEMP(IC_RESULT(ic)) &&
1272 applyToSet (cseSet,findPrevIc,ic,&pdic);
1275 /* if found then eliminate this and add to*/
1276 /* to cseSet an element containing result */
1277 /* of this with previous opcode */
1280 if (IS_ITEMP(IC_RESULT(ic))) {
1282 /* replace in the remaining of this block */
1283 replaceAllSymBySym(ic->next,IC_RESULT(ic),IC_RESULT(pdic));
1284 /* remove this iCode from inexpressions of all
1285 its successors, it cannot be in the in expressions
1286 of any of the predecessors */
1287 for (i = 0 ; i < count ;ebbs[i++]->visited = 0);
1288 applyToSet(ebb->succList,removeFromInExprs,ic,IC_RESULT(ic),
1289 IC_RESULT(pdic),ebb);
1291 /* if this was moved from another block */
1292 /* then replace in those blocks too */
1293 if ( ic->movedFrom ) {
1295 for (owner = setFirstItem(ic->movedFrom); owner ;
1296 owner = setNextItem(ic->movedFrom))
1297 replaceAllSymBySym(owner->sch,IC_RESULT(ic),IC_RESULT(pdic));
1299 pdic->movedFrom = unionSets(pdic->movedFrom,ic->movedFrom,THROW_NONE);
1302 addSetHead (&cseSet,newCseDef(IC_RESULT(ic),pdic));
1305 /* eliminate this */
1306 remiCodeFromeBBlock (ebb,ic);
1311 if (IS_ITEMP(IC_RESULT(ic)))
1316 /* just add this as a previous expression except in */
1317 /* case of a pointer access in which case this is a */
1318 /* usage not a definition */
1319 if (! (POINTER_SET(ic)) && IC_RESULT(ic)){
1320 deleteItemIf (&cseSet, ifDefSymIsX,IC_RESULT(ic));
1321 addSetHead(&cseSet,newCseDef(IC_RESULT(ic),ic));
1327 /* if assignment to a parameter which is not
1328 mine and type is a pointer then delete
1329 pointerGets to take care of aliasing */
1330 if (ASSIGNMENT(ic) &&
1331 OTHERS_PARM(OP_SYMBOL(IC_RESULT(ic))) &&
1332 IS_PTR(operandType(IC_RESULT(ic)))) {
1333 deleteGetPointers(&cseSet,IC_RIGHT(ic),ebb);
1336 /* if this is a pointerget then see if we can replace
1337 this with a previously assigned pointer value */
1338 if (POINTER_GET(ic) &&
1339 !(IS_BITFIELD(OP_SYMBOL(IC_RESULT(ic))->etype) ||
1340 isOperandVolatile(IC_LEFT(ic),TRUE))) {
1342 applyToSet(ptrSetSet,findPointerSet,IC_LEFT(ic),&pdop);
1343 /* if we find it then locally replace all
1344 references to the result with what we assigned */
1346 replaceAllSymBySym(ic->next,IC_RESULT(ic),pdop);
1350 /* delete from the cseSet anything that has */
1351 /* operands matching the result of this */
1352 /* except in case of pointer access */
1353 if (!(POINTER_SET(ic)) && IC_RESULT(ic)) {
1354 deleteItemIf (&cseSet,ifOperandsHave,IC_RESULT(ic));
1355 /* delete any previous definitions */
1356 ebb->defSet = bitVectCplAnd (ebb->defSet,OP_DEFS(IC_RESULT(ic)));
1360 /* add the left & right to the defUse set */
1361 if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic))) {
1362 OP_USES(IC_LEFT(ic)) =
1363 bitVectSetBit (OP_USES(IC_LEFT(ic)),ic->key);
1364 setUsesDefs(IC_LEFT(ic),ebb->defSet,ebb->outDefs,&ebb->usesDefs);
1368 if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic))) {
1369 OP_USES(IC_RIGHT(ic)) =
1370 bitVectSetBit (OP_USES(IC_RIGHT(ic)),ic->key);
1371 setUsesDefs(IC_RIGHT(ic),ebb->defSet,ebb->outDefs,&ebb->usesDefs);
1375 /* for the result it is special case, put the result */
1376 /* in the defuseSet if it a pointer or array access */
1377 if ( POINTER_SET(defic) ) {
1378 OP_USES(IC_RESULT(ic)) =
1379 bitVectSetBit (OP_USES(IC_RESULT(ic)),ic->key);
1380 setUsesDefs(IC_RESULT(ic),ebb->defSet,ebb->outDefs,&ebb->usesDefs);
1381 deleteItemIf(&cseSet,ifPointerGet,IC_RESULT(ic));
1382 ebb->ptrsSet = bitVectSetBit(ebb->ptrsSet,IC_RESULT(ic)->key);
1383 /* delete from inexpressions of all successors which
1384 have dfNum > than this block */
1385 for (i = 0 ; i < count ;ebbs[i++]->visited = 0);
1386 applyToSet(ebb->succList,delGetPointerSucc,IC_RESULT(ic),ebb->dfnum);
1388 /* delete from cseSet all other pointer sets
1390 deleteItemIf(&ptrSetSet,ifPointerSet,IC_RESULT(ic));
1391 /* add to the local pointerset set */
1392 addSetHead(&ptrSetSet,newCseDef(IC_RESULT(ic),ic));
1394 else /* add the result to defintion set */
1395 if (IC_RESULT(ic)) {
1396 OP_DEFS(IC_RESULT(ic)) =
1397 bitVectSetBit (OP_DEFS(IC_RESULT(ic)),ic->key);
1398 ebb->defSet = bitVectSetBit (ebb->defSet,ic->key);
1399 ebb->outDefs= bitVectCplAnd (ebb->outDefs,OP_DEFS(IC_RESULT(ic)));
1400 ebb->ldefs = bitVectSetBit (ebb->ldefs,ic->key);
1404 /* if this is an addressof instruction then */
1405 /* put the symbol in the address of list & */
1406 /* delete it from the cseSet */
1407 if (defic->op == ADDRESS_OF) {
1408 addSetHead (&ebb->addrOf, IC_LEFT(ic));
1409 deleteItemIf(&cseSet,ifDefSymIsX,IC_LEFT(ic));
1413 setToNull ((void **)&ebb->outExprs);
1414 ebb->outExprs = cseSet;
1415 ebb->outDefs = bitVectUnion (ebb->outDefs,ebb->defSet);
1416 ebb->ptrsSet = bitVectUnion (ebb->ptrsSet,ebb->inPtrsSet);
1420 /*-----------------------------------------------------------------*/
1421 /* cseAllBlocks - will sequentially go thru & do cse for all blocks*/
1422 /*-----------------------------------------------------------------*/
1423 int cseAllBlocks (eBBlock **ebbs,int count)
1428 /* if optimization turned off */
1430 for (i = 0 ; i < count ;i++ )
1431 change += cseBBlock (ebbs[i],FALSE,ebbs,count);