1 /*-------------------------------------------------------------------------
2 SDCCopt.c - calls all the optimizations routines and does some of the
3 hackier transformations, these include translating iCodes
4 to function calls and replacing local variables with their
5 register equivalents etc. Also contains the driver routine
6 for dead code elimination
8 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
10 This program is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 In other words, you are welcome to use, share and improve this program.
25 You are forbidden to forbid anyone else to use, share and improve
26 what you give them. Help stamp out software-hoarding!
27 -------------------------------------------------------------------------*/
31 /*-----------------------------------------------------------------*/
32 /* global variables */
38 /*-----------------------------------------------------------------*/
39 /* printSymName - prints the symbol names */
40 /*-----------------------------------------------------------------*/
41 int printSymName (void *vsym)
44 fprintf (stdout, " %s ", sym->name);
48 /*-----------------------------------------------------------------*/
49 /* cnvToFcall - does the actual conversion to function call */
50 /*-----------------------------------------------------------------*/
51 static void cnvToFcall (iCode *ic,eBBlock *ebp)
58 int lineno = ic->lineno;
60 ip = ic->next ; /* insertion point */
61 /* remove it from the iCode */
62 remiCodeFromeBBlock (ebp,ic);
100 /* if float support routines NOT compiled as reentrant */
101 if (! options.float_rent) {
104 if (IS_REGPARM(func->args->etype)) {
105 newic = newiCode(SEND,IC_LEFT(ic),NULL);
107 newic = newiCode('=',NULL,IC_LEFT(ic));
108 IC_RESULT(newic) = operandFromValue(func->args);
111 addiCodeToeBBlock(ebp,newic,ip);
112 newic->lineno = lineno;
115 if (IS_REGPARM(func->args->next->etype)) {
116 newic = newiCode(SEND,IC_LEFT(ic),NULL);
118 newic = newiCode('=',NULL,IC_RIGHT(ic));
119 IC_RESULT(newic) = operandFromValue(func->args->next);
121 addiCodeToeBBlock(ebp,newic,ip);
122 newic->lineno = lineno;
127 if (IS_REGPARM(func->args->next->etype)) {
128 newic = newiCode(SEND,right,NULL);
130 newic = newiCode(IPUSH,right,NULL);
134 addiCodeToeBBlock (ebp,newic,ip);
135 newic->lineno = lineno;
137 /* insert push left */
138 if (IS_REGPARM(func->args->etype)) {
139 newic = newiCode(SEND,left,NULL);
141 newic = newiCode(IPUSH,left,NULL);
144 addiCodeToeBBlock (ebp,newic,ip);
145 newic->lineno = lineno;
147 /* insert the call */
148 newic = newiCode(CALL,operandFromSymbol(func),NULL);
149 IC_RESULT(newic) = IC_RESULT(ic);
150 addiCodeToeBBlock(ebp,newic,ip);
151 newic->lineno = lineno;
154 /*-----------------------------------------------------------------*/
155 /* cnvToFloatCast - converts casts to floats to function calls */
156 /*-----------------------------------------------------------------*/
157 static void cnvToFloatCast (iCode *ic, eBBlock *ebp)
161 link *type = operandType(IC_RIGHT(ic));
162 int linenno = ic->lineno;
165 /* remove it from the iCode */
166 remiCodeFromeBBlock (ebp,ic);
167 /* depending on the type */
168 if (checkType(type,charType) == 1)
171 if (checkType(type,ucharType) == 1)
174 if (checkType(type,intType) == 1)
177 if (checkType(type,uintType) == 1)
180 if (checkType(type,longType) == 1)
185 /* if float support routines NOT compiled as reentrant */
186 if (! options.float_rent) {
188 if (IS_REGPARM(func->args->etype))
189 newic = newiCode(SEND,IC_RIGHT(ic),NULL);
191 newic = newiCode('=',NULL,IC_RIGHT(ic));
192 IC_RESULT(newic) = operandFromValue(func->args);
194 addiCodeToeBBlock(ebp,newic,ip);
195 newic->lineno = linenno;
199 if (IS_REGPARM(func->args->etype))
200 newic = newiCode(SEND,IC_RIGHT(ic),NULL);
202 newic = newiCode(IPUSH,IC_RIGHT(ic),NULL);
205 addiCodeToeBBlock(ebp,newic,ip);
206 newic->lineno = linenno;
211 newic = newiCode(CALL,operandFromSymbol(func),NULL);
212 IC_RESULT(newic) = IC_RESULT(ic);
213 addiCodeToeBBlock(ebp,newic,ip);
214 newic->lineno = linenno;
218 /*-----------------------------------------------------------------*/
219 /* cnvFromFloatCast - converts casts From floats to function calls */
220 /*-----------------------------------------------------------------*/
221 static void cnvFromFloatCast (iCode *ic, eBBlock *ebp)
225 link *type = operandType(IC_LEFT(ic));
226 int lineno = ic->lineno ;
229 /* remove it from the iCode */
230 remiCodeFromeBBlock (ebp,ic);
232 /* depending on the type */
233 if (checkType(type,charType) == 1)
236 if (checkType(type,ucharType) == 1)
239 if (checkType(type,intType) == 1)
242 if (checkType(type,uintType) == 1)
245 if (checkType(type,longType) == 1)
250 /* if float support routines NOT compiled as reentrant */
251 if (! options.float_rent) {
253 if (IS_REGPARM(func->args->etype))
254 newic = newiCode(SEND,IC_RIGHT(ic),NULL);
256 newic = newiCode('=',NULL,IC_RIGHT(ic));
257 IC_RESULT(newic) = operandFromValue(func->args);
259 addiCodeToeBBlock(ebp,newic,ip);
260 newic->lineno = lineno;
265 if (IS_REGPARM(func->args->etype))
266 newic = newiCode(SEND,IC_RIGHT(ic),NULL);
268 newic = newiCode(IPUSH,IC_RIGHT(ic),NULL);
271 addiCodeToeBBlock(ebp,newic,ip);
272 newic->lineno = lineno;
277 newic = newiCode(CALL,operandFromSymbol(func),NULL);
278 IC_RESULT(newic) = IC_RESULT(ic);
279 addiCodeToeBBlock(ebp,newic,ip);
280 newic->lineno = lineno;
284 /*-----------------------------------------------------------------*/
285 /* convilong - converts int or long mults or divs to fcalls */
286 /*-----------------------------------------------------------------*/
287 static void convilong (iCode *ic, eBBlock *ebp, link *type, int op)
290 iCode *ip = ic->next;
292 int lineno = ic->lineno;
294 remiCodeFromeBBlock (ebp,ic);
296 /* depending on the type */
297 if (checkType(type,intType) == 1)
298 func = (op == '*' ? __mulsint :
299 (op == '%' ? __modsint :__divsint));
301 if (checkType(type,uintType) == 1)
302 func = (op == '*' ? __muluint :
303 (op == '%' ? __moduint : __divuint));
305 if (checkType(type,longType) == 1)
306 func = (op == '*' ? __mulslong :
307 (op == '%' ? __modslong : __divslong));
309 func = (op == '*'? __mululong :
310 (op == '%' ? __modulong : __divulong));
312 /* if int & long support routines NOT compiled as reentrant */
313 if (! options.intlong_rent) {
315 if (IS_REGPARM(func->args->etype))
316 newic = newiCode(SEND,IC_LEFT(ic),NULL);
318 newic = newiCode('=',NULL,IC_LEFT(ic));
319 IC_RESULT(newic) = operandFromValue(func->args);
321 addiCodeToeBBlock(ebp,newic,ip);
322 newic->lineno = lineno;
325 if (IS_REGPARM(func->args->next->etype))
326 newic = newiCode(SEND,IC_RIGHT(ic),NULL);
328 newic = newiCode('=',NULL,IC_RIGHT(ic));
329 IC_RESULT(newic) = operandFromValue(func->args->next);
331 addiCodeToeBBlock(ebp,newic,ip);
332 newic->lineno = lineno;
337 /* compiled as reentrant then push */
339 if (IS_REGPARM(func->args->next->etype))
340 newic = newiCode(SEND,IC_RIGHT(ic),NULL);
342 newic = newiCode(IPUSH,IC_RIGHT(ic),NULL);
345 addiCodeToeBBlock (ebp,newic,ip);
346 newic->lineno = lineno;
348 /* insert push left */
349 if (IS_REGPARM(func->args->etype))
350 newic = newiCode(SEND,IC_LEFT(ic),NULL);
352 newic = newiCode(IPUSH,IC_LEFT(ic),NULL);
355 addiCodeToeBBlock (ebp,newic,ip);
356 newic->lineno = lineno;
361 newic = newiCode(CALL,operandFromSymbol(func),NULL);
362 IC_RESULT(newic) = IC_RESULT(ic);
363 addiCodeToeBBlock(ebp,newic,ip);
364 newic->lineno = lineno;
368 /*-----------------------------------------------------------------*/
369 /* convertToFcall - converts some operations to fcalls */
370 /*-----------------------------------------------------------------*/
371 static void convertToFcall (eBBlock **ebbs, int count)
375 /* for all blocks do */
376 for (i = 0 ; i < count ; i++ ) {
379 /* for all instructions in the block do */
380 for (ic = ebbs[i]->sch ; ic ; ic = ic->next ) {
382 /* floating point operations are
383 converted to function calls */
384 if ((IS_CONDITIONAL(ic) ||
385 IS_ARITHMETIC_OP(ic) ) &&
386 (IS_FLOAT(operandType(IC_RIGHT(ic))))) {
388 cnvToFcall(ic,ebbs[i]);
391 /* casting is a little different */
392 if (ic->op == CAST ) {
393 if (IS_FLOAT(operandType(IC_RIGHT(ic))))
394 cnvFromFloatCast (ic,ebbs[i]);
396 if (IS_FLOAT(operandType(IC_LEFT(ic))))
397 cnvToFloatCast (ic,ebbs[i]);
400 /* if long / int mult or divide or mod */
401 if (ic->op == '*' || ic->op == '/' || ic->op == '%' ) {
403 link *type = operandType(IC_LEFT(ic));
404 if (IS_INTEGRAL(type) && getSize(type) > 1)
405 convilong (ic,ebbs[i],type,ic->op);
411 /*-----------------------------------------------------------------*/
412 /* replaceRegEqv - replace all local variables with their reqv */
413 /*-----------------------------------------------------------------*/
414 static void replaceRegEqv ( eBBlock **ebbs, int count)
418 for (i = 0 ; i < count ; i++ ) {
422 for (ic = ebbs[i]->sch ; ic ; ic = ic->next) {
429 if (IS_TRUE_SYMOP(IC_COND(ic)) &&
430 OP_REQV(IC_COND(ic)))
431 IC_COND(ic) = opFromOpWithDU(OP_REQV(IC_COND(ic)),
432 OP_SYMBOL(IC_COND(ic))->defs,
433 OP_SYMBOL(IC_COND(ic))->uses);
438 if (ic->op == JUMPTABLE) {
439 if (IS_TRUE_SYMOP(IC_JTCOND(ic)) &&
440 OP_REQV(IC_JTCOND(ic)))
441 IC_JTCOND(ic) = opFromOpWithDU(OP_REQV(IC_JTCOND(ic)),
442 OP_SYMBOL(IC_JTCOND(ic))->defs,
443 OP_SYMBOL(IC_JTCOND(ic))->uses);
447 if (ic->op == RECEIVE) {
448 if (OP_SYMBOL(IC_RESULT(ic))->addrtaken)
449 OP_SYMBOL(IC_RESULT(ic))->isspilt = 1;
454 IS_TRUE_SYMOP(IC_RESULT(ic)) &&
455 OP_REQV(IC_RESULT(ic)) ) {
456 if (POINTER_SET(ic)) {
457 IC_RESULT(ic) = opFromOpWithDU(OP_REQV(IC_RESULT(ic)),
458 OP_SYMBOL(IC_RESULT(ic))->defs,
459 OP_SYMBOL(IC_RESULT(ic))->uses);
460 IC_RESULT(ic)->isaddr = 1;
462 IC_RESULT(ic) = opFromOpWithDU(OP_REQV(IC_RESULT(ic)),
463 OP_SYMBOL(IC_RESULT(ic))->defs,
464 OP_SYMBOL(IC_RESULT(ic))->uses);
468 IS_TRUE_SYMOP(IC_RIGHT(ic)) &&
469 OP_REQV(IC_RIGHT(ic)) ) {
470 IC_RIGHT(ic) = opFromOpWithDU(OP_REQV(IC_RIGHT(ic)),
471 OP_SYMBOL(IC_RIGHT(ic))->defs,
472 OP_SYMBOL(IC_RIGHT(ic))->uses);
473 IC_RIGHT(ic)->isaddr = 0;
477 IS_TRUE_SYMOP(IC_LEFT(ic)) &&
478 OP_REQV(IC_LEFT(ic)) ) {
479 IC_LEFT(ic) = opFromOpWithDU(OP_REQV(IC_LEFT(ic)),
480 OP_SYMBOL(IC_LEFT(ic))->defs,
481 OP_SYMBOL(IC_LEFT(ic))->uses);
482 IC_LEFT(ic)->isaddr = 0;
488 /*-----------------------------------------------------------------*/
489 /* killDeadCode - eliminates dead assignments */
490 /*-----------------------------------------------------------------*/
491 int killDeadCode ( eBBlock **ebbs, int count)
498 /* basic algorithm :- */
499 /* first the exclusion rules :- */
500 /* 1. if result is a global or volatile then skip */
501 /* 2. if assignment and result is a temp & isaddr then skip */
502 /* since this means array & pointer access, will be taken */
503 /* care of by alias analysis. */
504 /* 3. if the result is used in the remainder of the block skip*/
505 /* 4. if this definition does not reach the end of the block */
506 /* i.e. the result is not present in the outExprs then KILL*/
507 /* 5. if it reaches the end of block & is used by some success*/
510 /* this whole process is carried on iteratively till no change */
514 /* for all blocks do */
515 for ( i = 0 ; i < count ; i++ ) {
518 /* for all instructions in the block do */
519 for ( ic = ebbs[i]->sch ; ic ; ic = ic->next ) {
528 /* if the result is volatile then continue */
529 if (IC_RESULT(ic) && isOperandVolatile(IC_RESULT(ic),FALSE))
532 /* if the result is a temp & isaddr then skip */
533 if (IC_RESULT(ic) && POINTER_SET(ic))
536 /* if the result is used in the remainder of the */
537 /* block then skip */
538 if (usedInRemaining (IC_RESULT(ic),ic->next))
541 /* does this definition reach the end of the block
542 or the usage is zero then we can kill */
543 if (! bitVectBitValue(ebbs[i]->outDefs,ic->key))
544 kill = 1; /* if not we can kill it */
546 /* if this is a global variable or function parameter */
547 /* we cannot kill anyway */
548 if (isOperandGlobal(IC_RESULT(ic)) ||
549 (OP_SYMBOL(IC_RESULT(ic))->_isparm &&
550 !OP_SYMBOL(IC_RESULT(ic))->ismyparm))
553 /* if we are sure there are no usages */
554 if (bitVectIsZero(OP_USES(IC_RESULT(ic)))) {
559 /* reset visited flag */
560 for(j=0; j < count ; ebbs[j++]->visited = 0);
562 /* find out if this definition is alive */
563 if ( applyToSet (ebbs[i]->succList,
572 /* kill this one if required */
577 remiCodeFromeBBlock(ebbs[i],ic);
579 /* now delete from defUseSet */
580 deleteItemIf (&ebbs[i]->outExprs,ifDiCodeIsX,ic);
581 bitVectUnSetBit (ebbs[i]->outDefs,ic->key);
583 /* and defset of the block */
584 bitVectUnSetBit (ebbs[i]->defSet,ic->key);
586 /* for the left & right remove the usage */
587 if (IS_SYMOP(IC_LEFT(ic)))
588 bitVectUnSetBit(OP_USES(IC_LEFT(ic)),ic->key);
590 if (IS_SYMOP(IC_RIGHT(ic)))
591 bitVectUnSetBit(OP_USES(IC_RIGHT(ic)),ic->key);
594 } /* end of all instructions */
596 if (!ebbs[i]->sch && !ebbs[i]->noPath)
597 disconBBlock(ebbs[i],ebbs,count);
599 } /* end of for all blocks */
603 } /* end of while(1) */
608 /*-----------------------------------------------------------------*/
609 /* printCyclomatic - prints the cyclomatic information */
610 /*-----------------------------------------------------------------*/
611 static void printCyclomatic (eBBlock **ebbs, int count)
613 int nEdges = elementsInSet(graphEdges);
616 for (i = 0 ; i < count ; i++)
617 nNodes += (! ebbs[i]->noPath);
619 /* print the information */
620 werror(I_CYCLOMATIC,currFunc->name,nEdges,nNodes, nEdges - nNodes + 2);
623 /*-----------------------------------------------------------------*/
624 /* canOverlayLocals - returns true if the local variables can overlayed */
625 /*-----------------------------------------------------------------*/
626 static bool canOverlayLocals (eBBlock **ebbs, int count)
629 /* if staticAuto is in effect or the current function
630 being compiled is reentrant or the overlay segment
631 is empty or no overlay option is in effect then */
632 if (options.noOverlay ||
635 (IS_RENT(currFunc->etype) ||
636 IS_ISR(currFunc->etype))) ||
637 elementsInSet(overlay->syms) == 0)
641 /* otherwise do thru the blocks and see if there
642 any function calls if found then return false */
643 for (i = 0; i < count ; i++ ) {
646 for (ic = ebbs[i]->sch; ic ; ic = ic->next)
647 if (ic && ( ic->op == CALL || ic->op == PCALL))
651 /* no function calls found return TRUE */
656 /*-----------------------------------------------------------------*/
657 /* eBBlockFromiCode - creates extended basic blocks from iCode */
658 /* will return an array of eBBlock pointers */
659 /*-----------------------------------------------------------------*/
660 eBBlock **eBBlockFromiCode (iCode *ic)
662 eBBlock **ebbs = NULL ;
670 /* if nothing passed then return nothing */
677 /* optimize the chain for labels & gotos
678 this will eliminate redundant labels and
679 will change jump to jumps by jumps */
680 ic = iCodeLabelOptimize (ic);
682 /* break it down into basic blocks */
683 ebbs = iCodeBreakDown (ic,&count);
686 /* compute the control flow */
687 computeControlFlow (ebbs,count,0);
689 /* dumpraw if asked for */
690 if (options.dump_raw)
691 dumpEbbsToFileExt(".dumpraw0",ebbs,count);
693 /* replace the local variables with their
694 register equivalents : the liveRange computation
695 along with the register allocation will determine
696 if it finally stays in the registers */
697 replaceRegEqv (ebbs,count);
699 /* create loop regions */
700 loops = createLoopRegions (ebbs,count);
702 /* dumpraw if asked for */
703 if (options.dump_raw)
704 dumpEbbsToFileExt(".dumpraw1",ebbs,count);
706 /* do common subexpression elimination for each block */
707 change = cseAllBlocks(ebbs,saveCount);
709 /* dumpraw if asked for */
710 if (options.dump_raw)
711 dumpEbbsToFileExt(".dumpcse",ebbs,count);
713 /* compute the data flow */
714 computeDataFlow (ebbs,saveCount);
716 /* dumpraw if asked for */
717 if (options.dump_raw)
718 dumpEbbsToFileExt(".dumpdflow",ebbs,count);
720 /* global common subexpression elimination */
721 if ( optimize.global_cse ) {
722 change += cseAllBlocks(ebbs,saveCount);
723 if (options.dump_gcse)
724 dumpEbbsToFileExt(".dumpgcse",ebbs,saveCount);
727 kchange = killDeadCode (ebbs, saveCount);
729 if (options.dump_kill)
730 dumpEbbsToFileExt(".dumpdeadcode",ebbs,count);
732 /* do loop optimizations */
733 change += (lchange = loopOptimizations (loops,ebbs,count));
734 if (options.dump_loop)
735 dumpEbbsToFileExt(".dumploop",ebbs,count);
737 /* recompute the data flow and apply global cse again
738 if loops optimizations or dead code caused a change:
739 loops will brings out of the loop which then may be
740 available for use in the later blocks: dead code
741 elimination could potentially disconnect some blocks
742 conditional flow may be efected so we need to apply
743 subexpression once more */
744 if ( lchange || kchange ) {
746 computeDataFlow (ebbs,saveCount);
747 change += cseAllBlocks(ebbs,saveCount);
748 if (options.dump_loop)
749 dumpEbbsToFileExt(".dumploopg",ebbs,count);
751 /* if loop optimizations caused a change then do
752 dead code elimination once more : this will
753 get rid of the extra assignments to the induction
754 variables created during loop optimizations */
755 killDeadCode (ebbs, saveCount);
757 if (options.dump_loop)
758 dumpEbbsToFileExt(".dumploopd",ebbs,count);
763 /* sort it back by block number */
764 qsort (ebbs,saveCount,sizeof(eBBlock *),bbNumCompare);
766 /* if cyclomatic info requested then print it */
767 if (options.cyclomatic)
768 printCyclomatic(ebbs,saveCount);
771 /* convert operations with support routines
772 written in C to function calls : Iam doing
773 this at this point since I want all the
774 operations to be as they are for optimzations */
775 convertToFcall (ebbs,count);
777 /* check if the parameters and local variables
778 of this function can be put in the overlay segment
779 This check is essentially to see if the function
780 calls any other functions if yes then we cannot
782 if (canOverlayLocals(ebbs,count))
783 /* if we can then put the parameters &
784 local variables in the overlay set */
787 /* otherwise put them into data where
791 /* compute the live ranges */
792 computeLiveRanges (ebbs,count);
794 if (options.dump_range)
795 dumpEbbsToFileExt(".dumprange",ebbs,count);
797 /* allocate registers & generate code */
798 port->assignRegisters(ebbs,count);
800 /* throw away blocks */
801 setToNull ((void **)&graphEdges);
807 /* (add-hook 'c-mode-hook (lambda () (setq c-basic-offset 4))) */