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 -------------------------------------------------------------------------*/
28 /*-----------------------------------------------------------------*/
29 /* newCseDef - new cseDef */
30 /*-----------------------------------------------------------------*/
32 newCseDef (operand * sym, iCode * ic)
37 cdp = Safe_alloc (sizeof (cseDef));
48 /*-----------------------------------------------------------------*/
49 /* int isCseDefEqual - two definitions are equal */
50 /*-----------------------------------------------------------------*/
52 isCseDefEqual (void *vsrc, void *vdest)
60 return (src->key == dest->key &&
61 src->diCode == dest->diCode);
65 /*-----------------------------------------------------------------*/
66 /* pcseDef - in the cseDef */
67 /*-----------------------------------------------------------------*/
69 pcseDef (void *item, va_list ap)
77 fprintf (stdout, "**null op**");
78 printOperand (cdp->sym, stdout);
79 icTab = getTableEntry (cdp->diCode->op);
80 icTab->iCodePrint (stdout, cdp->diCode, icTab->printName);
84 /*-----------------------------------------------------------------*/
85 /* replaceAllSymBySym - replaces all operands by operand in an */
86 /* instruction chain */
87 /*-----------------------------------------------------------------*/
89 replaceAllSymBySym (iCode * ic, operand * from, operand * to, bitVect ** ndpset)
93 for (lic = ic; lic; lic = lic->next)
97 /* do the special cases first */
101 IC_COND (lic)->key == from->key)
104 bitVectUnSetBit (OP_USES (from), lic->key);
105 OP_USES (to) = bitVectSetBit (OP_USES (to), lic->key);
106 siaddr = IC_COND (lic)->isaddr;
107 IC_COND (lic) = operandFromOperand (to);
108 IC_COND (lic)->isaddr = siaddr;
114 if (lic->op == JUMPTABLE)
117 IC_JTCOND (lic)->key == from->key)
120 bitVectUnSetBit (OP_USES (from), lic->key);
121 OP_USES (to) = bitVectSetBit (OP_USES (to), lic->key);
122 siaddr = IC_COND (lic)->isaddr;
123 IC_JTCOND (lic) = operandFromOperand (to);
124 IC_JTCOND (lic)->isaddr = siaddr;
130 if (IC_RESULT (lic) && IC_RESULT (lic)->key == from->key)
132 /* maintain du chains */
133 if (POINTER_SET (lic))
135 bitVectUnSetBit (OP_USES (from), lic->key);
136 OP_USES (to) = bitVectSetBit (OP_USES (to), lic->key);
138 /* also check if the "from" was in the non-dominating
139 pointer sets and replace it with "to" in the bitVector */
140 if (bitVectBitValue (*ndpset, from->key))
142 bitVectUnSetBit (*ndpset, from->key);
143 bitVectSetBit (*ndpset, to->key);
149 bitVectUnSetBit (OP_DEFS (from), lic->key);
150 OP_DEFS (to) = bitVectSetBit (OP_DEFS (to), lic->key);
152 siaddr = IC_RESULT (lic)->isaddr;
153 IC_RESULT (lic) = operandFromOperand (to);
154 IC_RESULT (lic)->isaddr = siaddr;
158 IC_RIGHT (lic) && IC_RIGHT (lic)->key == from->key)
160 bitVectUnSetBit (OP_USES (from), lic->key);
161 OP_USES (to) = bitVectSetBit (OP_USES (to), lic->key);
162 siaddr = IC_RIGHT (lic)->isaddr;
163 IC_RIGHT (lic) = operandFromOperand (to);
164 IC_RIGHT (lic)->isaddr = siaddr;
168 IC_LEFT (lic) && IC_LEFT (lic)->key == from->key)
170 bitVectUnSetBit (OP_USES (from), lic->key);
171 OP_USES (to) = bitVectSetBit (OP_USES (to), lic->key);
172 siaddr = IC_LEFT (lic)->isaddr;
173 IC_LEFT (lic) = operandFromOperand (to);
174 IC_LEFT (lic)->isaddr = siaddr;
179 /*-----------------------------------------------------------------*/
180 /* iCodeKeyIs - if the icode keys match then return 1 */
181 /*-----------------------------------------------------------------*/
182 DEFSETFUNC (iCodeKeyIs)
187 if (cdp->diCode->key == key)
193 /*-----------------------------------------------------------------*/
194 /* removeFromInExprs - removes an icode from inexpressions */
195 /*-----------------------------------------------------------------*/
196 DEFSETFUNC (removeFromInExprs)
200 V_ARG (operand *, from);
201 V_ARG (operand *, to);
202 V_ARG (eBBlock *, cbp);
208 deleteItemIf (&ebp->inExprs, iCodeKeyIs, ic->key);
209 if (ebp != cbp && !bitVectBitValue (cbp->domVect, ebp->bbnum))
210 replaceAllSymBySym (ebp->sch, from, to, &ebp->ndompset);
212 applyToSet (ebp->succList, removeFromInExprs, ic, from, to, cbp);
216 /*-----------------------------------------------------------------*/
217 /* isGlobalInNearSpace - return TRUE if valriable is a globalin data */
218 /*-----------------------------------------------------------------*/
220 isGlobalInNearSpace (operand * op)
222 sym_link *type = getSpec (operandType (op));
223 /* this is 8051 specific: optimization
224 suggested by Jean-Louis VERN, with 8051s we have no
225 advantage of putting variables in near space into
227 if (isOperandGlobal (op) && !IN_FARSPACE (SPEC_OCLS (type)) &&
228 IN_DIRSPACE (SPEC_OCLS (type)))
234 /*-----------------------------------------------------------------*/
235 /* findCheaperOp - cseBBlock support routine, will check to see if */
236 /* we have a operand previously defined */
237 /*-----------------------------------------------------------------*/
238 DEFSETFUNC (findCheaperOp)
241 V_ARG (operand *, cop);
242 V_ARG (operand **, opp);
244 /* if we have already found it */
248 /* not found it yet check if this is the one */
249 /* and this is not the defining one */
250 if (cop->key == cdp->key)
253 /* do a special check this will help in */
254 /* constant propagation & dead code elim */
255 /* for assignments only */
256 if (cdp->diCode->op == '=') {
257 /* if the result is volatile then return result */
258 if (IS_OP_VOLATILE (IC_RESULT (cdp->diCode)))
259 *opp = IC_RESULT (cdp->diCode);
261 /* if this is a straight assignment and
262 left is a temp then prefer the temporary to the
264 if (!POINTER_SET (cdp->diCode) &&
265 IS_ITEMP (IC_RESULT (cdp->diCode)) &&
266 IS_TRUE_SYMOP (IC_RIGHT (cdp->diCode)))
267 *opp = IC_RESULT (cdp->diCode);
269 /* if straight assignement && and both
270 are temps then prefer the one that
271 will not need extra space to spil, also
272 take into consideration if right side
273 an induction variable
275 if (!POINTER_SET (cdp->diCode) &&
276 IS_ITEMP (IC_RESULT (cdp->diCode)) &&
277 IS_ITEMP (IC_RIGHT (cdp->diCode)) &&
278 !OP_SYMBOL (IC_RIGHT (cdp->diCode))->isind &&
279 ((!SPIL_LOC (IC_RIGHT (cdp->diCode)) &&
280 SPIL_LOC (IC_RESULT (cdp->diCode))) ||
281 (SPIL_LOC (IC_RESULT (cdp->diCode)) &&
282 SPIL_LOC (IC_RESULT (cdp->diCode)) ==
283 SPIL_LOC (IC_RIGHT (cdp->diCode)))))
284 *opp = IC_RESULT (cdp->diCode);
286 *opp = IC_RIGHT (cdp->diCode);
290 *opp = IC_RESULT (cdp->diCode);
293 /* if this is an assign to a temp. then check
294 if the right side is this then return this */
295 if (IS_TRUE_SYMOP (cop) &&
296 cdp->diCode->op == '=' &&
297 !POINTER_SET (cdp->diCode) &&
298 cop->key == IC_RIGHT (cdp->diCode)->key &&
299 !isGlobalInNearSpace (IC_RIGHT (cdp->diCode)) &&
300 IS_ITEMP (IC_RESULT (cdp->diCode)))
301 *opp = IC_RESULT (cdp->diCode);
304 (isOperandLiteral(*opp) ||
305 (SPEC_USIGN(operandType (cop))==SPEC_USIGN(operandType (*opp)) &&
306 (SPEC_LONG(operandType (cop))==SPEC_LONG(operandType (*opp))))))
309 if ((isGlobalInNearSpace (cop) &&
310 !isOperandLiteral (*opp)) ||
311 isOperandVolatile (*opp, FALSE)
318 if (cop->key == (*opp)->key)
324 if ((*opp)->isaddr != cop->isaddr && IS_ITEMP (cop))
326 *opp = operandFromOperand (*opp);
327 (*opp)->isaddr = cop->isaddr;
337 /*-----------------------------------------------------------------*/
338 /* findPointerSet - finds the right side of a pointer set op */
339 /*-----------------------------------------------------------------*/
340 DEFSETFUNC (findPointerSet)
343 V_ARG (operand *, op);
344 V_ARG (operand **, opp);
345 V_ARG (operand *, rop);
347 if (POINTER_SET (cdp->diCode) &&
348 IC_RESULT (cdp->diCode)->key == op->key &&
349 !isOperandVolatile (IC_RESULT (cdp->diCode), TRUE) &&
350 !isOperandVolatile (IC_RIGHT (cdp->diCode), TRUE) &&
351 getSize (operandType (IC_RIGHT (cdp->diCode))) ==
352 getSize (operandType (rop)))
354 *opp = IC_RIGHT (cdp->diCode);
361 /*-----------------------------------------------------------------*/
362 /* findPrevIc - cseBBlock support function will return the iCode */
363 /* which matches the current one */
364 /*-----------------------------------------------------------------*/
365 DEFSETFUNC (findPrevIc)
369 V_ARG (iCode **, icp);
371 /* if already found */
375 /* if the iCodes are the same */
376 if (isiCodeEqual (ic, cdp->diCode) &&
377 isOperandEqual (cdp->sym, IC_RESULT (cdp->diCode)))
383 /* if iCodes are not the same */
384 /* see the operands maybe interchanged */
385 if (ic->op == cdp->diCode->op &&
386 (ic->op == '+' || ic->op == '*') &&
387 isOperandEqual (IC_LEFT (ic), IC_RIGHT (cdp->diCode)) &&
388 isOperandEqual (IC_RIGHT (ic), IC_LEFT (cdp->diCode)))
397 /*-------------------------------------------------------------------*/
398 /* ifAssignedFromGlobal - if definition is an assignment from global */
399 /*-------------------------------------------------------------------*/
400 DEFSETFUNC (ifAssignedFromGlobal)
403 iCode *dic=cdp->diCode;
405 if (dic->op=='=' && isOperandGlobal(IC_RIGHT(dic))) {
411 /*-----------------------------------------------------------------*/
412 /* ifDefGlobal - if definition is global */
413 /*-----------------------------------------------------------------*/
414 DEFSETFUNC (ifDefGlobal)
418 return (isOperandGlobal (cdp->sym));
421 /*-----------------------------------------------------------------*/
422 /* ifAnyGetPointer - if get pointer icode */
423 /*-----------------------------------------------------------------*/
424 DEFSETFUNC (ifAnyGetPointer)
428 if (cdp->diCode && POINTER_GET (cdp->diCode))
433 /*-----------------------------------------------------------------*/
434 /* ifOperandsHave - if any of the operand are the same as this */
435 /*-----------------------------------------------------------------*/
436 DEFSETFUNC (ifOperandsHave)
439 V_ARG (operand *, op);
442 if (IC_LEFT (cdp->diCode) &&
443 IS_SYMOP (IC_LEFT (cdp->diCode)) &&
444 IC_LEFT (cdp->diCode)->key == op->key)
447 if (IC_RIGHT (cdp->diCode) &&
448 IS_SYMOP (IC_RIGHT (cdp->diCode)) &&
449 IC_RIGHT (cdp->diCode)->key == op->key)
452 /* or if any of the operands are volatile */
453 if (IC_LEFT (cdp->diCode) &&
454 IS_OP_VOLATILE (IC_LEFT (cdp->diCode)))
457 if (IC_RIGHT (cdp->diCode) &&
458 IS_OP_VOLATILE (IC_RIGHT (cdp->diCode)))
462 if (IC_RESULT (cdp->diCode) &&
463 IS_OP_VOLATILE (IC_RESULT (cdp->diCode)))
469 /*-----------------------------------------------------------------*/
470 /* ifDefSymIs - if a definition is found in the set */
471 /*-----------------------------------------------------------------*/
473 ifDefSymIs (set * cseSet, operand * sym)
478 if (!sym || !IS_SYMOP (sym))
480 for (sl = cseSet; sl; sl = sl->next)
483 if (loop->sym->key == sym->key)
490 /*-----------------------------------------------------------------*/
491 /* ifDefSymIsX - will return 1 if the symbols match */
492 /*-----------------------------------------------------------------*/
493 DEFSETFUNC (ifDefSymIsX)
496 V_ARG (operand *, op);
499 return cdp->sym->key == op->key;
501 return (isOperandEqual (cdp->sym, op));
506 /*-----------------------------------------------------------------*/
507 /* ifDiCodeIs - returns truw if diCode is same */
508 /*-----------------------------------------------------------------*/
510 ifDiCodeIs (set * cseSet, iCode * ic)
518 for (sl = cseSet; sl; sl = sl->next)
521 if (loop->diCode == ic)
528 /*-----------------------------------------------------------------*/
529 /* ifPointerGet - returns true if the icode is pointer get sym */
530 /*-----------------------------------------------------------------*/
531 DEFSETFUNC (ifPointerGet)
534 V_ARG (operand *, op);
535 iCode *dic = cdp->diCode;
536 operand *left = IC_LEFT (cdp->diCode);
538 if (POINTER_GET (dic) && left->key == op->key)
544 /*-----------------------------------------------------------------*/
545 /* ifPointerSet - returns true if the icode is pointer set sym */
546 /*-----------------------------------------------------------------*/
547 DEFSETFUNC (ifPointerSet)
550 V_ARG (operand *, op);
552 if (POINTER_SET (cdp->diCode) &&
553 IC_RESULT (cdp->diCode)->key == op->key)
559 /*-----------------------------------------------------------------*/
560 /* ifDiCodeIsX - will return 1 if the symbols match */
561 /*-----------------------------------------------------------------*/
562 DEFSETFUNC (ifDiCodeIsX)
567 return cdp->diCode == ic;
571 /*-----------------------------------------------------------------*/
572 /* algebraicOpts - does some algebraic optimizations */
573 /*-----------------------------------------------------------------*/
575 algebraicOpts (iCode * ic)
577 /* we don't deal with the following iCodes
588 /* if both operands present & ! IFX */
589 /* then if they are both literal we */
590 /* perform the operation right now */
591 if (IC_RESULT (ic) &&
594 IS_OP_LITERAL (IC_LEFT (ic)) &&
595 IS_OP_LITERAL (IC_RIGHT (ic)))
598 IC_RIGHT (ic) = operandOperation (IC_LEFT (ic),
601 operandType (IC_RESULT (ic)));
604 SET_RESULT_RIGHT (ic);
608 /* if not ifx & only one operand present */
609 if (IC_RESULT (ic) &&
611 IS_OP_LITERAL (IC_LEFT (ic)) &&
615 IC_RIGHT (ic) = operandOperation (IC_LEFT (ic),
618 operandType (IC_RESULT (ic)));
621 SET_RESULT_RIGHT (ic);
626 /* a special case : or in short a kludgy solution will think
627 about a better solution over a glass of wine someday */
628 if (ic->op == GET_VALUE_AT_ADDRESS)
631 if (IS_ITEMP (IC_RESULT (ic)) &&
632 IS_TRUE_SYMOP (IC_LEFT (ic)))
636 IC_RIGHT (ic) = operandFromOperand (IC_LEFT (ic));
637 IC_RIGHT (ic)->isaddr = 0;
639 IC_RESULT (ic) = operandFromOperand (IC_RESULT (ic));
640 IC_RESULT (ic)->isaddr = 0;
641 setOperandType (IC_RESULT (ic), operandType (IC_RIGHT (ic)));
645 if (IS_ITEMP (IC_LEFT (ic)) &&
646 IS_ITEMP (IC_RESULT (ic)) &&
647 /* !OP_SYMBOL(IC_RESULT(ic))->isreqv && */
648 /* !OP_SYMBOL(IC_LEFT(ic))->isreqv && */
649 !IC_LEFT (ic)->isaddr)
652 IC_RIGHT (ic) = operandFromOperand (IC_LEFT (ic));
653 IC_RIGHT (ic)->isaddr = 0;
654 IC_RESULT (ic) = operandFromOperand (IC_RESULT (ic));
655 IC_RESULT (ic)->isaddr = 0;
663 /* depending on the operation */
667 /* if adding the same thing change to left shift by 1 */
668 if (IC_LEFT (ic)->key == IC_RIGHT (ic)->key &&
669 !IS_FLOAT (operandType (IC_RESULT (ic))))
672 IC_RIGHT (ic) = operandFromLit (1);
675 /* if addition then check if one of them is a zero */
676 /* if yes turn it into assignmnt */
677 if (IS_OP_LITERAL (IC_LEFT (ic)) &&
678 operandLitValue (IC_LEFT (ic)) == 0.0)
683 SET_ISADDR (IC_RESULT (ic), 0);
684 SET_ISADDR (IC_RIGHT (ic), 0);
687 if (IS_OP_LITERAL (IC_RIGHT (ic)) &&
688 operandLitValue (IC_RIGHT (ic)) == 0.0)
692 IC_RIGHT (ic) = IC_LEFT (ic);
694 SET_ISADDR (IC_RIGHT (ic), 0);
695 SET_ISADDR (IC_RESULT (ic), 0);
700 /* if subtracting the the same thing then zero */
701 if (IC_LEFT (ic)->key == IC_RIGHT (ic)->key)
704 IC_RIGHT (ic) = operandFromLit (0);
706 IC_RESULT (ic) = operandFromOperand (IC_RESULT (ic));
707 IC_RESULT (ic)->isaddr = 0;
711 /* if subtraction then check if one of the operand */
712 /* is zero then depending on which operand change */
713 /* to assignment or unary minus */
714 if (IS_OP_LITERAL (IC_RIGHT (ic)) &&
715 operandLitValue (IC_RIGHT (ic)) == 0.0)
717 /* right size zero change to assignment */
719 IC_RIGHT (ic) = IC_LEFT (ic);
721 SET_ISADDR (IC_RIGHT (ic), 0);
722 SET_ISADDR (IC_RESULT (ic), 0);
725 if (IS_OP_LITERAL (IC_LEFT (ic)) &&
726 operandLitValue (IC_LEFT (ic)) == 0.0)
728 /* left zero turn into an unary minus */
730 IC_LEFT (ic) = IC_RIGHT (ic);
731 IC_RIGHT (ic) = NULL;
735 /* if multiplication then check if either of */
736 /* them is zero then the result is zero */
737 /* if either of them is one then result is */
740 if (IS_OP_LITERAL (IC_LEFT (ic)))
743 if (operandLitValue (IC_LEFT (ic)) == 0.0)
746 IC_RIGHT (ic) = IC_LEFT (ic);
748 SET_RESULT_RIGHT (ic);
751 if (operandLitValue (IC_LEFT (ic)) == 1.0)
755 SET_RESULT_RIGHT (ic);
760 if (IS_OP_LITERAL (IC_RIGHT (ic)))
763 if (operandLitValue (IC_RIGHT (ic)) == 0.0)
767 SET_RESULT_RIGHT (ic);
771 if (operandLitValue (IC_RIGHT (ic)) == 1.0)
774 IC_RIGHT (ic) = IC_LEFT (ic);
776 SET_RESULT_RIGHT (ic);
782 /* if division by self then 1 */
783 if (IC_LEFT (ic)->key == IC_RIGHT (ic)->key)
786 IC_RIGHT (ic) = operandFromLit (1);
788 IC_RESULT (ic) = operandFromOperand (IC_RESULT (ic));
789 IC_RESULT (ic)->isaddr = 0;
791 /* if this is a division then check if right */
792 /* is one then change it to an assignment */
793 if (IS_OP_LITERAL (IC_RIGHT (ic)) &&
794 operandLitValue (IC_RIGHT (ic)) == 1.0)
798 IC_RIGHT (ic) = IC_LEFT (ic);
800 SET_RESULT_RIGHT (ic);
804 /* if both are the same for an comparison operators */
808 if (isOperandEqual (IC_LEFT (ic), IC_RIGHT (ic)))
811 IC_RIGHT (ic) = operandFromLit (1);
813 SET_RESULT_RIGHT (ic);
819 if (isOperandEqual (IC_LEFT (ic), IC_RIGHT (ic)))
822 IC_RIGHT (ic) = operandFromLit (0);
824 SET_RESULT_RIGHT (ic);
829 sym_link *otype = operandType(IC_RIGHT(ic));
830 sym_link *ctype = operandType(IC_LEFT(ic));
831 /* if this is a cast of a literal value */
832 if (IS_OP_LITERAL (IC_RIGHT (ic)) &&
833 !(IS_GENPTR(ctype) && (IS_PTR(otype) && !IS_GENPTR(otype)))) {
836 operandFromValue (valCastLiteral (operandType (IC_LEFT (ic)),
837 operandLitValue (IC_RIGHT (ic))));
839 SET_ISADDR (IC_RESULT (ic), 0);
841 /* if casting to the same */
842 if (compareType (operandType (IC_RESULT (ic)),
843 operandType (IC_RIGHT (ic))) == 1) {
846 SET_ISADDR (IC_RESULT (ic), 0);
851 if (IS_OP_LITERAL (IC_LEFT (ic)))
855 (operandLitValue (IC_LEFT (ic)) == 0 ?
856 operandFromLit (1) : operandFromLit (0));
858 SET_ISADDR (IC_RESULT (ic), 0);
864 #define OTHERS_PARM(s) (s->_isparm && !s->ismyparm)
865 /*-----------------------------------------------------------------*/
866 /* updateSpillLocation - keeps track of register spill location */
867 /*-----------------------------------------------------------------*/
869 updateSpillLocation (iCode * ic, int induction)
874 if (POINTER_SET (ic))
880 /* for the form true_symbol := iTempNN */
881 if (ASSIGN_ITEMP_TO_SYM (ic) &&
882 !SPIL_LOC (IC_RIGHT (ic))) {
884 setype = getSpec (operandType (IC_RESULT (ic)));
886 if (!OP_SYMBOL(IC_RIGHT (ic))->noSpilLoc &&
887 !IS_VOLATILE (setype) &&
888 !IN_FARSPACE (SPEC_OCLS (setype)) &&
889 !OTHERS_PARM (OP_SYMBOL (IC_RESULT (ic))))
891 SPIL_LOC (IC_RIGHT (ic)) =
892 IC_RESULT (ic)->operand.symOperand;
895 if (ASSIGN_ITEMP_TO_ITEMP (ic)) {
897 if (!SPIL_LOC (IC_RIGHT (ic)) &&
898 !bitVectBitsInCommon (OP_DEFS (IC_RIGHT (ic)), OP_USES (IC_RESULT (ic))) &&
899 OP_SYMBOL (IC_RESULT (ic))->isreqv) {
901 setype = getSpec (operandType (IC_RESULT (ic)));
903 if (!OP_SYMBOL(IC_RIGHT (ic))->noSpilLoc &&
904 !IS_VOLATILE (setype) &&
905 !IN_FARSPACE (SPEC_OCLS (setype)) &&
906 !OTHERS_PARM (OP_SYMBOL (IC_RESULT (ic))))
908 SPIL_LOC (IC_RIGHT (ic)) =
909 SPIL_LOC (IC_RESULT (ic));
911 /* special case for inductions */
913 OP_SYMBOL(IC_RIGHT(ic))->isreqv &&
914 !OP_SYMBOL(IC_RESULT (ic))->noSpilLoc &&
915 !SPIL_LOC(IC_RESULT(ic))) {
916 SPIL_LOC (IC_RESULT (ic)) = SPIL_LOC (IC_RIGHT (ic));
920 /*-----------------------------------------------------------------*/
921 /* setUsesDef - sets the uses def bitvector for a given operand */
922 /*-----------------------------------------------------------------*/
924 setUsesDefs (operand * op, bitVect * bdefs,
925 bitVect * idefs, bitVect ** oud)
927 /* compute the definitions alive at this point */
928 bitVect *adefs = bitVectUnion (bdefs, idefs);
930 /* of these definitions find the ones that are */
931 /* for this operand */
932 adefs = bitVectIntersect (adefs, OP_DEFS (op));
934 /* these are the definitions that this operand can use */
935 op->usesDefs = adefs;
937 /* the out defs is an union */
938 *oud = bitVectUnion (*oud, adefs);
941 /*-----------------------------------------------------------------*/
942 /* unsetDefsAndUses - clear this operation for the operands */
943 /*-----------------------------------------------------------------*/
945 unsetDefsAndUses (iCode * ic)
947 if (ic->op == JUMPTABLE)
950 /* take away this definition from the def chain of the */
951 /* result & take away from use set of the operands */
954 /* turn off def set */
955 if (IS_SYMOP (IC_RESULT (ic)))
957 if (!POINTER_SET (ic))
958 bitVectUnSetBit (OP_DEFS (IC_RESULT (ic)), ic->key);
960 bitVectUnSetBit (OP_USES (IC_RESULT (ic)), ic->key);
962 /* turn off the useSet for the operands */
963 if (IS_SYMOP (IC_LEFT (ic)))
964 bitVectUnSetBit (OP_USES (IC_LEFT (ic)), ic->key);
966 if (IS_SYMOP (IC_RIGHT (ic)))
967 bitVectUnSetBit (OP_USES (IC_RIGHT (ic)), ic->key);
970 /* must be ifx turn off the use */ if (IS_SYMOP (IC_COND (ic)))
971 bitVectUnSetBit (OP_USES (IC_COND (ic)), ic->key);
974 /*-----------------------------------------------------------------*/
975 /* ifxOptimize - changes ifx conditions if it can */
976 /*-----------------------------------------------------------------*/
978 ifxOptimize (iCode * ic, set * cseSet,
980 eBBlock * ebb, int *change,
981 eBBlock ** ebbs, int count)
986 /* if the condition can be replaced */
990 applyToSetFTrue (cseSet, findCheaperOp, IC_COND (ic), &pdop);
998 /* if the conditional is a literal then */
999 if (IS_OP_LITERAL (IC_COND (ic)))
1002 if ((operandLitValue (IC_COND (ic)) != 0.0) && IC_TRUE (ic))
1005 /* change to a goto */
1007 IC_LABEL (ic) = IC_TRUE (ic);
1014 if (!operandLitValue (IC_COND (ic)) && IC_FALSE (ic))
1017 IC_LABEL (ic) = IC_FALSE (ic);
1023 /* then kill this if condition */
1024 remiCodeFromeBBlock (ebb, ic);
1028 /* now we need to recompute the control flow */
1029 /* since the control flow has changed */
1030 /* this is very expensive but it does not happen */
1031 /* too often, if it does happen then the user pays */
1033 computeControlFlow (ebbs, count, 1);
1034 if (!options.lessPedantic) {
1035 werror (W_CONTROL_FLOW, ic->filename, ic->lineno);
1040 /* if there is only one successor and that successor
1041 is the same one we are conditionally going to then
1042 we can remove this conditional statement */
1043 label = (IC_TRUE (ic) ? IC_TRUE (ic) : IC_FALSE (ic));
1044 if (elementsInSet (ebb->succList) == 1 &&
1045 isinSet (ebb->succList, eBBWithEntryLabel (ebbs, label, count)))
1048 remiCodeFromeBBlock (ebb, ic);
1049 computeControlFlow (ebbs, count, 1);
1050 if (!options.lessPedantic) {
1051 werror (W_CONTROL_FLOW, ic->filename, ic->lineno);
1057 /* if it remains an IFX the update the use Set */
1058 OP_USES (IC_COND (ic)) = bitVectSetBit (OP_USES (IC_COND (ic)), ic->key);
1059 setUsesDefs (IC_COND (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs);
1063 /*-----------------------------------------------------------------*/
1064 /* diCodeForSym - finds the definiting instruction for a symbol */
1065 /*-----------------------------------------------------------------*/
1066 DEFSETFUNC (diCodeForSym)
1069 V_ARG (operand *, sym);
1070 V_ARG (iCode **, dic);
1072 /* if already found */
1076 /* if not if this is the defining iCode */
1077 if (sym->key == cdp->key)
1086 /*-----------------------------------------------------------------*/
1087 /* constFold - does some constant folding */
1088 /*-----------------------------------------------------------------*/
1090 constFold (iCode * ic, set * cseSet)
1094 /* this routine will change
1100 /* deal with only + & - */
1101 if (ic->op != '+' &&
1105 /* this check is a hueristic to prevent live ranges
1106 from becoming too long */
1107 if (IS_PTR (operandType (IC_RESULT (ic))))
1110 /* check if operation with a literal */
1111 if (!IS_OP_LITERAL (IC_RIGHT (ic)))
1114 /* check if we can find a definition for the
1116 if (!(applyToSet (cseSet, diCodeForSym, IC_LEFT (ic), &dic)))
1119 /* check that this is also a +/- */
1120 if (dic->op != '+' && dic->op != '-')
1123 /* with a literal */
1124 if (!IS_OP_LITERAL (IC_RIGHT (dic)))
1127 /* find the definition of the left operand
1128 of dic.then check if this defined with a
1129 get_pointer return 0 if the pointer size is
1130 less than 2 (MCS51 specific) */
1131 if (!(applyToSet (cseSet, diCodeForSym, IC_LEFT (dic), &ldic)))
1134 if (POINTER_GET (ldic) && getSize (operandType (IC_LEFT (ldic))) <= 1)
1137 /* it is if the operations are the same */
1138 /* the literal parts need to be added */
1139 IC_LEFT (ic) = operandFromOperand (IC_LEFT (dic));
1140 if (ic->op == dic->op)
1141 IC_RIGHT (ic) = operandFromLit (operandLitValue (IC_RIGHT (ic)) +
1142 operandLitValue (IC_RIGHT (dic)));
1144 IC_RIGHT (ic) = operandFromLit (operandLitValue (IC_RIGHT (ic)) -
1145 operandLitValue (IC_RIGHT (dic)));
1147 if (IS_ITEMP (IC_RESULT (ic)))
1149 SPIL_LOC (IC_RESULT (ic)) = NULL;
1150 OP_SYMBOL(IC_RESULT (ic))->noSpilLoc = 1;
1157 /*-----------------------------------------------------------------*/
1158 /* deleteGetPointers - called when a pointer is passed as parm */
1159 /* will delete from cseSet all get pointers computed from this */
1160 /* pointer. A simple ifOperandsHave is not good enough here */
1161 /*-----------------------------------------------------------------*/
1163 deleteGetPointers (set ** cseSet, set ** pss, operand * op, eBBlock * ebb)
1165 set *compItems = NULL;
1170 if (!*cseSet && !*pss)
1173 /* first find all items computed from this operand .
1174 This done fairly simply go thru the list and find
1175 those that are computed by arthimetic with this
1177 for (cdp = setFirstItem (*cseSet); cdp; cdp = setNextItem (*cseSet))
1179 if (IS_ARITHMETIC_OP (cdp->diCode))
1181 if (isOperandEqual (IC_LEFT (cdp->diCode), op) ||
1182 isOperandEqual (IC_RIGHT (cdp->diCode), op))
1184 /* save it in our list of items */
1185 addSet (&compItems, IC_RESULT (cdp->diCode));
1187 /* also check for those computed from our computed
1188 list . This will take care of situations like
1189 iTemp1 = iTemp0 + 8;
1190 iTemp2 = iTemp1 + 8; */
1191 if (isinSetWith (compItems, (void*)IC_LEFT (cdp->diCode),
1192 (insetwithFunc)isOperandEqual) ||
1193 isinSetWith (compItems, (void*)IC_RIGHT (cdp->diCode),
1194 (insetwithFunc)isOperandEqual))
1196 addSet (&compItems, IC_RESULT (cdp->diCode));
1201 /* now delete all pointer gets with this op */
1202 deleteItemIf (cseSet, ifPointerGet, op);
1203 deleteItemIf (pss, ifPointerSet, op);
1205 /* set the bit vector used by dataFlow computation later */
1206 ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, op->key);
1207 /* now for the computed items */
1208 for (cop = setFirstItem (compItems); cop; cop = setNextItem (compItems))
1210 ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, cop->key);
1211 deleteItemIf (cseSet, ifPointerGet, cop);
1212 deleteItemIf (pss, ifPointerSet, cop);
1216 /*-----------------------------------------------------------------*/
1217 /* delGetPointerSucc - delete get pointer from inExprs of succ with */
1218 /* dfnum > supplied */
1219 /*-----------------------------------------------------------------*/
1220 DEFSETFUNC (delGetPointerSucc)
1222 eBBlock *ebp = item;
1223 V_ARG (operand *, op);
1230 if (ebp->dfnum > dfnum)
1232 deleteItemIf (&ebp->inExprs, ifPointerGet, op);
1235 return applyToSet (ebp->succList, delGetPointerSucc, op, dfnum);
1238 /*-----------------------------------------------------------------*/
1239 /* fixUpTypes - KLUGE HACK fixup a lowering problem */
1240 /*-----------------------------------------------------------------*/
1242 fixUpTypes (iCode * ic)
1244 sym_link *t1 = operandType (IC_LEFT (ic)), *t2;
1246 /* if (TARGET_IS_DS390) */
1247 if (options.model == MODEL_FLAT24)
1253 /* for pointer_gets if the types of result & left r the
1254 same then change it type of result to next */
1256 compareType (t2 = operandType (IC_RESULT (ic)), t1) == 1)
1258 setOperandType (IC_RESULT (ic), t2->next);
1262 /*-----------------------------------------------------------------*/
1263 /* cseBBlock - common subexpression elimination for basic blocks */
1264 /* this is the hackiest kludgiest routine in the whole */
1265 /* system. also the most important, since almost all */
1266 /* data flow related information is computed by it */
1267 /*-----------------------------------------------------------------*/
1269 cseBBlock (eBBlock * ebb, int computeOnly,
1270 eBBlock ** ebbs, int count)
1276 set *ptrSetSet = NULL;
1278 /* if this block is not reachable */
1282 /* set of common subexpressions */
1283 cseSet = setFromSet (ebb->inExprs);
1285 /* these will be computed by this routine */
1286 setToNull ((void **) &ebb->outDefs);
1287 setToNull ((void **) &ebb->defSet);
1288 setToNull ((void **) &ebb->usesDefs);
1289 setToNull ((void **) &ebb->ptrsSet);
1290 setToNull ((void **) &ebb->addrOf);
1291 setToNull ((void **) &ebb->ldefs);
1293 ebb->outDefs = bitVectCopy (ebb->inDefs);
1294 bitVectDefault = iCodeKey;
1295 ebb->defSet = newBitVect (iCodeKey);
1296 ebb->usesDefs = newBitVect (iCodeKey);
1298 /* for all the instructions in this block do */
1299 for (ic = ebb->sch; ic; ic = ic->next)
1306 ic->eBBlockNum = ebb->bbnum;
1311 /* if this is an assignment from true symbol
1312 to a temp then do pointer post inc/dec optimzation */
1313 if (ic->op == '=' && !POINTER_SET (ic) &&
1314 IS_PTR (operandType (IC_RESULT (ic))))
1316 ptrPostIncDecOpt (ic);
1319 /* clear the def & use chains for the operands involved */
1320 /* in this operation . since it can change due to opts */
1321 unsetDefsAndUses (ic);
1323 if (ic->op == PCALL || ic->op == CALL || ic->op == RECEIVE)
1325 /* add to defSet of the symbol */
1326 OP_DEFS (IC_RESULT (ic)) =
1327 bitVectSetBit (OP_DEFS (IC_RESULT (ic)), ic->key);
1328 /* add to the definition set of this block */
1329 ebb->defSet = bitVectSetBit (ebb->defSet, ic->key);
1330 ebb->ldefs = bitVectSetBit (ebb->ldefs, ic->key);
1331 ebb->outDefs = bitVectCplAnd (ebb->outDefs, OP_DEFS (IC_RESULT (ic)));
1332 setUsesDefs (IC_RESULT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs);
1333 /* delete global variables from the cseSet
1334 since they can be modified by the function call */
1335 deleteItemIf (&cseSet, ifDefGlobal);
1337 /* and also itemps assigned from globals */
1338 deleteItemIf (&cseSet, ifAssignedFromGlobal);
1340 /* delete all getpointer iCodes from cseSet, this should
1341 be done only for global arrays & pointers but at this
1342 point we don't know if globals, so to be safe do all */
1343 deleteItemIf (&cseSet, ifAnyGetPointer);
1346 /* for pcall & ipush we need to add to the useSet */
1347 if ((ic->op == PCALL ||
1351 IS_SYMOP (IC_LEFT (ic)))
1354 /* check if they can be replaced */
1358 applyToSetFTrue (cseSet, findCheaperOp, IC_LEFT (ic), &pdop);
1360 IC_LEFT (ic) = pdop;
1362 /* the lookup could have changed it */
1363 if (IS_SYMOP (IC_LEFT (ic)))
1365 OP_USES (IC_LEFT (ic)) =
1366 bitVectSetBit (OP_USES (IC_LEFT (ic)), ic->key);
1367 setUsesDefs (IC_LEFT (ic), ebb->defSet,
1368 ebb->outDefs, &ebb->usesDefs);
1372 /* if we a sending a pointer as a parameter
1373 then kill all cse since the pointed to item
1374 might be changed in the function being called */
1375 if ((ic->op == IPUSH || ic->op == SEND) &&
1376 IS_PTR (operandType (IC_LEFT (ic))))
1378 deleteGetPointers (&cseSet, &ptrSetSet, IC_LEFT (ic), ebb);
1379 ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, IC_LEFT (ic)->key);
1380 for (i = 0; i < count; ebbs[i++]->visited = 0);
1381 applyToSet (ebb->succList, delGetPointerSucc,
1382 IC_LEFT (ic), ebb->dfnum);
1387 /* if jumptable then mark the usage */
1388 if (ic->op == JUMPTABLE)
1390 OP_USES (IC_JTCOND (ic)) =
1391 bitVectSetBit (OP_USES (IC_JTCOND (ic)), ic->key);
1392 setUsesDefs (IC_JTCOND (ic), ebb->defSet,
1393 ebb->outDefs, &ebb->usesDefs);
1400 /* do some algebraic optimizations if possible */
1402 while (constFold (ic, cseSet));
1405 if (POINTER_GET (ic) && !IS_PTR (operandType (IC_LEFT (ic))))
1407 setOperandType (IC_LEFT (ic),
1408 aggrToPtr (operandType (IC_LEFT (ic)), FALSE));
1412 if (POINTER_SET (ic) && !IS_PTR (operandType (IC_RESULT (ic))))
1414 setOperandType (IC_RESULT (ic),
1415 aggrToPtr (operandType (IC_RESULT (ic)), FALSE));
1418 /* if this is a condition statment then */
1419 /* check if the condition can be replaced */
1422 ifxOptimize (ic, cseSet, computeOnly,
1428 /* if the assignment & result is a temp */
1429 /* see if we can replace it */
1433 /* update the spill location for this */
1434 updateSpillLocation (ic,0);
1436 if (POINTER_SET (ic) &&
1437 !(IS_BITFIELD (OP_SYMBOL (IC_RESULT (ic))->etype)))
1440 applyToSetFTrue (cseSet, findCheaperOp, IC_RESULT (ic), &pdop);
1441 if (pdop && IS_ITEMP (pdop) && !computeOnly)
1442 IC_RESULT (ic) = pdop;
1446 /* do the operand lookup i.e. for both the */
1447 /* right & left operand : check the cseSet */
1448 /* to see if they have been replaced if yes */
1449 /* then replace them with those from cseSet */
1451 /* and left is a symbol */
1452 if (IS_SYMOP (IC_LEFT (ic)) &&
1453 !computeOnly && ic->op != ADDRESS_OF)
1457 applyToSetFTrue (cseSet, findCheaperOp, IC_LEFT (ic), &pdop);
1460 if (POINTER_GET (ic))
1462 if (IS_ITEMP (pdop) || IS_OP_LITERAL (pdop))
1464 IC_LEFT (ic) = pdop;
1467 /* check if there is a pointer set
1468 for the same pointer visible if yes
1469 then change this into an assignment */
1471 if (applyToSetFTrue (cseSet, findPointerSet, IC_LEFT (ic), &pdop, IC_RESULT (ic)) &&
1472 !bitVectBitValue (ebb->ptrsSet, pdop->key))
1475 IC_LEFT (ic) = NULL;
1476 IC_RIGHT (ic) = pdop;
1477 SET_ISADDR (IC_RESULT (ic), 0);
1483 IC_LEFT (ic) = pdop;
1490 if (IS_SYMOP (IC_RIGHT (ic)) && !computeOnly)
1494 applyToSetFTrue (cseSet, findCheaperOp, IC_RIGHT (ic), &pdop);
1497 IC_RIGHT (ic) = pdop;
1502 /* if left or right changed then do algebraic */
1506 while (constFold (ic, cseSet));
1509 /* if after all this it becomes a assignment to self
1510 then delete it and continue */
1511 if (ASSIGNMENT_TO_SELF (ic))
1513 remiCodeFromeBBlock (ebb, ic);
1517 /* now we will check to see if the entire */
1518 /* operation has been performed before */
1519 /* and is available */
1520 /* don't do assignments they will be killed */
1521 /* by dead code elimination if required do */
1522 /* it only if result is a temporary */
1524 if (!(POINTER_GET (ic) &&
1525 (IS_BITFIELD (OP_SYMBOL (IC_RESULT (ic))->etype) ||
1526 isOperandVolatile (IC_LEFT (ic), TRUE) ||
1527 bitVectBitValue (ebb->ndompset, IC_LEFT (ic)->key))) &&
1529 IS_ITEMP (IC_RESULT (ic)) &&
1532 applyToSet (cseSet, findPrevIc, ic, &pdic);
1533 if (pdic && compareType (operandType (IC_RESULT (pdic)),
1534 operandType (IC_RESULT (ic))) != 1)
1536 if (pdic && port->cseOk && (*port->cseOk)(ic,pdic) == 0)
1540 /* Alternate code */
1541 if (pdic && IS_ITEMP(IC_RESULT(ic))) {
1542 /* if previous definition found change this to an assignment */
1545 IC_RIGHT(ic) = operandFromOperand(IC_RESULT(pdic));
1546 SET_ISADDR(IC_RESULT(ic),0);
1547 SET_ISADDR(IC_RIGHT (ic),0);
1550 if (!(POINTER_SET (ic)) && IC_RESULT (ic)) {
1551 deleteItemIf (&cseSet, ifDefSymIsX, IC_RESULT (ic));
1552 addSetHead (&cseSet, newCseDef (IC_RESULT (ic), ic));
1556 /* if assignment to a parameter which is not
1557 mine and type is a pointer then delete
1558 pointerGets to take care of aliasing */
1559 if (ASSIGNMENT (ic) &&
1560 OTHERS_PARM (OP_SYMBOL (IC_RESULT (ic))) &&
1561 IS_PTR (operandType (IC_RESULT (ic))))
1563 deleteGetPointers (&cseSet, &ptrSetSet, IC_RIGHT (ic), ebb);
1564 for (i = 0; i < count; ebbs[i++]->visited = 0);
1565 applyToSet (ebb->succList, delGetPointerSucc, IC_RIGHT (ic), ebb->dfnum);
1566 ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, IC_RIGHT (ic)->key);
1569 /* if this is a pointerget then see if we can replace
1570 this with a previously assigned pointer value */
1571 if (POINTER_GET (ic) &&
1572 !(IS_BITFIELD (OP_SYMBOL (IC_RESULT (ic))->etype) ||
1573 isOperandVolatile (IC_LEFT (ic), TRUE)))
1576 applyToSet (ptrSetSet, findPointerSet, IC_LEFT (ic), &pdop, IC_RESULT (ic));
1577 /* if we find it then locally replace all
1578 references to the result with what we assigned */
1581 replaceAllSymBySym (ic->next, IC_RESULT (ic), pdop, &ebb->ndompset);
1585 /* delete from the cseSet anything that has */
1586 /* operands matching the result of this */
1587 /* except in case of pointer access */
1588 if (!(POINTER_SET (ic)) && IC_RESULT (ic))
1590 deleteItemIf (&cseSet, ifOperandsHave, IC_RESULT (ic));
1591 /* delete any previous definitions */
1592 ebb->defSet = bitVectCplAnd (ebb->defSet, OP_DEFS (IC_RESULT (ic)));
1596 /* add the left & right to the defUse set */
1597 if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)))
1599 OP_USES (IC_LEFT (ic)) =
1600 bitVectSetBit (OP_USES (IC_LEFT (ic)), ic->key);
1601 setUsesDefs (IC_LEFT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs);
1605 if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)))
1607 OP_USES (IC_RIGHT (ic)) =
1608 bitVectSetBit (OP_USES (IC_RIGHT (ic)), ic->key);
1609 setUsesDefs (IC_RIGHT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs);
1613 /* for the result it is special case, put the result */
1614 /* in the defuseSet if it a pointer or array access */
1615 if (POINTER_SET (defic))
1617 OP_USES (IC_RESULT (ic)) =
1618 bitVectSetBit (OP_USES (IC_RESULT (ic)), ic->key);
1619 setUsesDefs (IC_RESULT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs);
1620 deleteItemIf (&cseSet, ifPointerGet, IC_RESULT (ic));
1621 ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, IC_RESULT (ic)->key);
1622 /* delete from inexpressions of all successors which
1623 have dfNum > than this block */
1624 for (i = 0; i < count; ebbs[i++]->visited = 0);
1625 applyToSet (ebb->succList, delGetPointerSucc, IC_RESULT (ic), ebb->dfnum);
1627 /* delete from cseSet all other pointer sets
1629 deleteItemIf (&ptrSetSet, ifPointerSet, IC_RESULT (ic));
1630 /* add to the local pointerset set */
1631 addSetHead (&ptrSetSet, newCseDef (IC_RESULT (ic), ic));
1634 /* add the result to defintion set */ if (IC_RESULT (ic))
1636 OP_DEFS (IC_RESULT (ic)) =
1637 bitVectSetBit (OP_DEFS (IC_RESULT (ic)), ic->key);
1638 ebb->defSet = bitVectSetBit (ebb->defSet, ic->key);
1639 ebb->outDefs = bitVectCplAnd (ebb->outDefs, OP_DEFS (IC_RESULT (ic)));
1640 ebb->ldefs = bitVectSetBit (ebb->ldefs, ic->key);
1644 /* if this is an addressof instruction then */
1645 /* put the symbol in the address of list & */
1646 /* delete it from the cseSet */
1647 if (defic->op == ADDRESS_OF)
1649 addSetHead (&ebb->addrOf, IC_LEFT (ic));
1650 deleteItemIf (&cseSet, ifDefSymIsX, IC_LEFT (ic));
1654 setToNull ((void **) &ebb->outExprs);
1655 ebb->outExprs = cseSet;
1656 ebb->outDefs = bitVectUnion (ebb->outDefs, ebb->defSet);
1657 ebb->ptrsSet = bitVectUnion (ebb->ptrsSet, ebb->inPtrsSet);
1661 /*-----------------------------------------------------------------*/
1662 /* cseAllBlocks - will sequentially go thru & do cse for all blocks */
1663 /*-----------------------------------------------------------------*/
1665 cseAllBlocks (eBBlock ** ebbs, int count)
1670 /* if optimization turned off */
1672 for (i = 0; i < count; i++)
1673 change += cseBBlock (ebbs[i], FALSE, ebbs, count);