X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCopt.c;h=d9183695512c6b1eb5ffa5e856800ffff9db9fca;hb=24db07e65dc37c465c586f173fcf7d591d5bd7bc;hp=23899f8969345ba15faf769ff72f8374733fa407;hpb=b09af35f2f1cde7649d3ac4a6f5d2af6d97895a0;p=fw%2Fsdcc diff --git a/src/SDCCopt.c b/src/SDCCopt.c index 23899f89..d9183695 100644 --- a/src/SDCCopt.c +++ b/src/SDCCopt.c @@ -25,31 +25,12 @@ You are forbidden to forbid anyone else to use, share and improve what you give them. Help stamp out software-hoarding! -------------------------------------------------------------------------*/ -#include -#include -#include "SDCCglobl.h" -#include "SDCCast.h" -#include "SDCCmem.h" -#include "SDCCy.h" -#include "SDCChasht.h" -#include "SDCCbitv.h" -#include "SDCCset.h" -#include "SDCCicode.h" -#include "SDCClabel.h" -#include "SDCCBBlock.h" -#include "SDCCloop.h" -#include "SDCCcse.h" -#include "SDCCcflow.h" -#include "SDCCdflow.h" -#include "SDCClrange.h" -#include "SDCCralloc.h" -#include "SDCCptropt.h" -#include "SDCCopt.h" +#include "common.h" /*-----------------------------------------------------------------*/ /* global variables */ -int cseDefNum = 0 ; +int cseDefNum = 0; char flowChanged = 0; @@ -57,372 +38,478 @@ char flowChanged = 0; /*-----------------------------------------------------------------*/ /* printSymName - prints the symbol names */ /*-----------------------------------------------------------------*/ -int printSymName (void *vsym) +int +printSymName (void *vsym) { - symbol *sym = vsym ; - fprintf (stdout, " %s ", sym->name); - return 0; + symbol *sym = vsym; + fprintf (stdout, " %s ", sym->name); + return 0; } /*-----------------------------------------------------------------*/ /* cnvToFcall - does the actual conversion to function call */ /*-----------------------------------------------------------------*/ -static void cnvToFcall (iCode *ic,eBBlock *ebp) +static void +cnvToFcall (iCode * ic, eBBlock * ebp) { - iCode *ip ; - iCode *newic; - operand *left ; - operand *right; - symbol *func = NULL; - int lineno = ic->lineno; - - ip = ic->next ; /* insertion point */ - /* remove it from the iCode */ - remiCodeFromeBBlock (ebp,ic); - - left = IC_LEFT(ic); - right= IC_RIGHT(ic); - - switch (ic->op) { - case '+' : - func = __fsadd ; - break; - case '-' : - func = __fssub; - break; - case '/' : - func = __fsdiv; - break; - case '*' : - func = __fsmul; - break; - case EQ_OP : - func = __fseq; - break; - case NE_OP : - func = __fsneq ; - break; - case '<' : - func = __fslt ; - break; + iCode *ip; + iCode *newic; + operand *left; + operand *right; + symbol *func = NULL; + int lineno = ic->lineno; + int bytesPushed=0; + + ip = ic->next; /* insertion point */ + /* remove it from the iCode */ + remiCodeFromeBBlock (ebp, ic); + + left = IC_LEFT (ic); + right = IC_RIGHT (ic); + + switch (ic->op) + { + case '+': + func = __fsadd; + break; + case '-': + func = __fssub; + break; + case '/': + func = __fsdiv; + break; + case '*': + func = __fsmul; + break; + case EQ_OP: + func = __fseq; + break; + case NE_OP: + func = __fsneq; + break; + case '<': + func = __fslt; + break; case '>': - func = __fsgt; - break; - case LE_OP : - func = __fslteq; - break; - case GE_OP : - func = __fsgteq ; - break; + func = __fsgt; + break; + case LE_OP: + func = __fslteq; + break; + case GE_OP: + func = __fsgteq; + break; } - /* if float support routines NOT compiled as reentrant */ - if (! options.float_rent) { - - /* first one */ - if (IS_REGPARM(func->args->etype)) { - newic = newiCode(SEND,IC_LEFT(ic),NULL); - } else { - newic = newiCode('=',NULL,IC_LEFT(ic)); - IC_RESULT(newic) = operandFromValue(func->args); + /* if float support routines NOT compiled as reentrant */ + if (!options.float_rent) + { + + /* first one */ + if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) + { + newic = newiCode (SEND, IC_LEFT (ic), NULL); + newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype); + } + else + { + newic = newiCode ('=', NULL, IC_LEFT (ic)); + IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)); } - addiCodeToeBBlock(ebp,newic,ip); - newic->lineno = lineno; + addiCodeToeBBlock (ebp, newic, ip); + newic->lineno = lineno; + + /* second one */ + if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype)) + { + newic = newiCode (SEND, IC_RIGHT (ic), NULL); + newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->next->etype); + } + else + { + newic = newiCode ('=', NULL, IC_RIGHT (ic)); + IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)->next); + } + addiCodeToeBBlock (ebp, newic, ip); + newic->lineno = lineno; - /* second one */ - if (IS_REGPARM(func->args->next->etype)) { - newic = newiCode(SEND,IC_LEFT(ic),NULL); - } else { - newic = newiCode('=',NULL,IC_RIGHT(ic)); - IC_RESULT(newic) = operandFromValue(func->args->next); + } + else + { + + /* push right */ + if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype)) + { + newic = newiCode (SEND, right, NULL); + newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->next->etype); } - addiCodeToeBBlock(ebp,newic,ip); - newic->lineno = lineno; - - } else { - - /* push right */ - if (IS_REGPARM(func->args->next->etype)) { - newic = newiCode(SEND,right,NULL); - } else { - newic = newiCode(IPUSH,right,NULL); - newic->parmPush = 1; + else + { + newic = newiCode (IPUSH, right, NULL); + newic->parmPush = 1; + bytesPushed+=4; } - addiCodeToeBBlock (ebp,newic,ip); - newic->lineno = lineno; + addiCodeToeBBlock (ebp, newic, ip); + newic->lineno = lineno; - /* insert push left */ - if (IS_REGPARM(func->args->etype)) { - newic = newiCode(SEND,left,NULL); - } else { - newic = newiCode(IPUSH,left,NULL); - newic->parmPush = 1; + /* insert push left */ + if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) + { + newic = newiCode (SEND, left, NULL); + newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype); + } + else + { + newic = newiCode (IPUSH, left, NULL); + newic->parmPush = 1; + bytesPushed+=4; } - addiCodeToeBBlock (ebp,newic,ip); - newic->lineno = lineno; + addiCodeToeBBlock (ebp, newic, ip); + newic->lineno = lineno; } - /* insert the call */ - newic = newiCode(CALL,operandFromSymbol(func),NULL); - IC_RESULT(newic) = IC_RESULT(ic); - addiCodeToeBBlock(ebp,newic,ip); - newic->lineno = lineno; + /* insert the call */ + newic = newiCode (CALL, operandFromSymbol (func), NULL); + IC_RESULT (newic) = IC_RESULT (ic); + newic->lineno = lineno; + newic->parmBytes+=bytesPushed; + addiCodeToeBBlock (ebp, newic, ip); } /*-----------------------------------------------------------------*/ /* cnvToFloatCast - converts casts to floats to function calls */ /*-----------------------------------------------------------------*/ -static void cnvToFloatCast (iCode *ic, eBBlock *ebp) -{ - iCode *ip, *newic; - symbol *func; - link *type = operandType(IC_RIGHT(ic)); - int linenno = ic->lineno; - - ip = ic->next ; - /* remove it from the iCode */ - remiCodeFromeBBlock (ebp,ic); - /* depending on the type */ - if (checkType(type,charType) == 1) - func = __char2fs ; - else - if (checkType(type,ucharType) == 1) - func = __uchar2fs; - else - if (checkType(type,intType) == 1) - func = __int2fs; - else - if (checkType(type,uintType) == 1) - func = __uint2fs ; - else - if (checkType(type,longType) == 1) - func = __long2fs; - else - func = __ulong2fs ; - - /* if float support routines NOT compiled as reentrant */ - if (! options.float_rent) { - /* first one */ - if (IS_REGPARM(func->args->etype)) - newic = newiCode(SEND,IC_RIGHT(ic),NULL); - else { - newic = newiCode('=',NULL,IC_RIGHT(ic)); - IC_RESULT(newic) = operandFromValue(func->args); +static void +cnvToFloatCast (iCode * ic, eBBlock * ebp) +{ + iCode *ip, *newic; + symbol *func = NULL; + sym_link *type = operandType (IC_RIGHT (ic)); + int linenno = ic->lineno; + int bwd, su; + + ip = ic->next; + /* remove it from the iCode */ + remiCodeFromeBBlock (ebp, ic); + /* depending on the type */ + for (bwd = 0; bwd < 3; bwd++) + { + for (su = 0; su < 2; su++) + { + if (compareType (type, __multypes[bwd][su]) == 1) + { + func = __conv[0][bwd][su]; + goto found; + } } - addiCodeToeBBlock(ebp,newic,ip); - newic->lineno = linenno; - - } else { - /* push the left */ - if (IS_REGPARM(func->args->etype)) - newic = newiCode(SEND,IC_RIGHT(ic),NULL); - else { - newic = newiCode(IPUSH,IC_RIGHT(ic),NULL); - newic->parmPush = 1; + } + assert (0); +found: + + /* if float support routines NOT compiled as reentrant */ + if (!options.float_rent) + { + /* first one */ + if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) + { + newic = newiCode (SEND, IC_RIGHT (ic), NULL); + newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype); + } + else + { + newic = newiCode ('=', NULL, IC_RIGHT (ic)); + IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)); + } + addiCodeToeBBlock (ebp, newic, ip); + newic->lineno = linenno; + + } + else + { + /* push the left */ + if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) { + newic = newiCode (SEND, IC_RIGHT (ic), NULL); + newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype); + } + else + { + newic = newiCode (IPUSH, IC_RIGHT (ic), NULL); + newic->parmPush = 1; } - addiCodeToeBBlock(ebp,newic,ip); - newic->lineno = linenno; - + addiCodeToeBBlock (ebp, newic, ip); + newic->lineno = linenno; + } - /* make the call */ - newic = newiCode(CALL,operandFromSymbol(func),NULL); - IC_RESULT(newic) = IC_RESULT(ic); - addiCodeToeBBlock(ebp,newic,ip); - newic->lineno = linenno; + /* make the call */ + newic = newiCode (CALL, operandFromSymbol (func), NULL); + IC_RESULT (newic) = IC_RESULT (ic); + addiCodeToeBBlock (ebp, newic, ip); + newic->lineno = linenno; } /*-----------------------------------------------------------------*/ /* cnvFromFloatCast - converts casts From floats to function calls */ /*-----------------------------------------------------------------*/ -static void cnvFromFloatCast (iCode *ic, eBBlock *ebp) +static void +cnvFromFloatCast (iCode * ic, eBBlock * ebp) { - iCode *ip, *newic; - symbol *func; - link *type = operandType(IC_LEFT(ic)); - int lineno = ic->lineno ; - - ip = ic->next ; - /* remove it from the iCode */ - remiCodeFromeBBlock (ebp,ic); - - /* depending on the type */ - if (checkType(type,charType) == 1) - func = __fs2char ; - else - if (checkType(type,ucharType) == 1) - func = __fs2uchar; - else - if (checkType(type,intType) == 1) - func = __fs2int; - else - if (checkType(type,uintType) == 1) - func = __fs2uint ; - else - if (checkType(type,longType) == 1) - func = __fs2long; - else - func = __fs2ulong ; - - /* if float support routines NOT compiled as reentrant */ - if (! options.float_rent) { - /* first one */ - if (IS_REGPARM(func->args->etype)) - newic = newiCode(SEND,IC_RIGHT(ic),NULL); - else { - newic = newiCode('=',NULL,IC_RIGHT(ic)); - IC_RESULT(newic) = operandFromValue(func->args); + iCode *ip, *newic; + symbol *func = NULL; + sym_link *type = operandType (IC_LEFT (ic)); + int lineno = ic->lineno; + int bwd, su; + + ip = ic->next; + /* remove it from the iCode */ + remiCodeFromeBBlock (ebp, ic); + + /* depending on the type */ + for (bwd = 0; bwd < 3; bwd++) + { + for (su = 0; su < 2; su++) + { + if (compareType (type, __multypes[bwd][su]) == 1) + { + func = __conv[1][bwd][su]; + goto found; + } + } + } + assert (0); +found: + + /* if float support routines NOT compiled as reentrant */ + if (!options.float_rent) + { + /* first one */ + if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) { + newic = newiCode (SEND, IC_RIGHT (ic), NULL); + newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype); + } + else + { + newic = newiCode ('=', NULL, IC_RIGHT (ic)); + IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)); } - addiCodeToeBBlock(ebp,newic,ip); - newic->lineno = lineno; + addiCodeToeBBlock (ebp, newic, ip); + newic->lineno = lineno; - } else { + } + else + { - /* push the left */ - if (IS_REGPARM(func->args->etype)) - newic = newiCode(SEND,IC_RIGHT(ic),NULL); - else { - newic = newiCode(IPUSH,IC_RIGHT(ic),NULL); - newic->parmPush = 1; + /* push the left */ + if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) { + newic = newiCode (SEND, IC_RIGHT (ic), NULL); + newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype); + } + else + { + newic = newiCode (IPUSH, IC_RIGHT (ic), NULL); + newic->parmPush = 1; } - addiCodeToeBBlock(ebp,newic,ip); - newic->lineno = lineno; + addiCodeToeBBlock (ebp, newic, ip); + newic->lineno = lineno; } - /* make the call */ - newic = newiCode(CALL,operandFromSymbol(func),NULL); - IC_RESULT(newic) = IC_RESULT(ic); - addiCodeToeBBlock(ebp,newic,ip); - newic->lineno = lineno; + /* make the call */ + newic = newiCode (CALL, operandFromSymbol (func), NULL); + IC_RESULT (newic) = IC_RESULT (ic); + addiCodeToeBBlock (ebp, newic, ip); + newic->lineno = lineno; } /*-----------------------------------------------------------------*/ /* convilong - converts int or long mults or divs to fcalls */ /*-----------------------------------------------------------------*/ -static void convilong (iCode *ic, eBBlock *ebp, link *type, int op) -{ - symbol *func; - iCode *ip = ic->next; - iCode *newic ; - int lineno = ic->lineno; - - remiCodeFromeBBlock (ebp,ic); - - /* depending on the type */ - if (checkType(type,intType) == 1) - func = (op == '*' ? __mulsint : - (op == '%' ? __modsint :__divsint)); - else - if (checkType(type,uintType) == 1) - func = (op == '*' ? __muluint : - (op == '%' ? __moduint : __divuint)); - else - if (checkType(type,longType) == 1) - func = (op == '*' ? __mulslong : - (op == '%' ? __modslong : __divslong)); - else - func = (op == '*'? __mululong : - (op == '%' ? __modulong : __divulong)); - - /* if int & long support routines NOT compiled as reentrant */ - if (! options.intlong_rent) { - /* first one */ - if (IS_REGPARM(func->args->etype)) - newic = newiCode(SEND,IC_LEFT(ic),NULL); - else { - newic = newiCode('=',NULL,IC_LEFT(ic)); - IC_RESULT(newic) = operandFromValue(func->args); +static void +convilong (iCode * ic, eBBlock * ebp, sym_link * type, int op) +{ + symbol *func = NULL; + iCode *ip = ic->next; + iCode *newic; + int lineno = ic->lineno; + int bwd; + int su; + int bytesPushed=0; + + remiCodeFromeBBlock (ebp, ic); + + /* depending on the type */ + for (bwd = 0; bwd < 3; bwd++) + { + for (su = 0; su < 2; su++) + { + if (compareType (type, __multypes[bwd][su]) == 1) + { + if (op == '*') + func = __muldiv[0][bwd][su]; + else if (op == '/') + func = __muldiv[1][bwd][su]; + else if (op == '%') + func = __muldiv[2][bwd][su]; + else if (op == RRC) + func = __rlrr[1][bwd][su]; + else if (op == RLC) + func = __rlrr[0][bwd][su]; + else if (op == RIGHT_OP) + func = __rlrr[1][bwd][su]; + else if (op == LEFT_OP) + func = __rlrr[0][bwd][su]; + else + assert (0); + goto found; + } } - addiCodeToeBBlock(ebp,newic,ip); - newic->lineno = lineno; - - /* second one */ - if (IS_REGPARM(func->args->next->etype)) - newic = newiCode(SEND,IC_RIGHT(ic),NULL); - else { - newic = newiCode('=',NULL,IC_RIGHT(ic)); - IC_RESULT(newic) = operandFromValue(func->args->next); + } + assert (0); +found: + /* if int & long support routines NOT compiled as reentrant */ + if (!options.intlong_rent) + { + /* first one */ + if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) { + newic = newiCode (SEND, IC_LEFT (ic), NULL); + newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype); } - addiCodeToeBBlock(ebp,newic,ip); - newic->lineno = lineno; - - - } else { - - /* compiled as reentrant then push */ - /* push right */ - if (IS_REGPARM(func->args->next->etype)) - newic = newiCode(SEND,IC_RIGHT(ic),NULL); - else { - newic = newiCode(IPUSH,IC_RIGHT(ic),NULL); - newic->parmPush = 1; + else + { + newic = newiCode ('=', NULL, IC_LEFT (ic)); + IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)); } - addiCodeToeBBlock (ebp,newic,ip); - newic->lineno = lineno; - - /* insert push left */ - if (IS_REGPARM(func->args->etype)) - newic = newiCode(SEND,IC_LEFT(ic),NULL); - else { - newic = newiCode(IPUSH,IC_LEFT(ic),NULL); - newic->parmPush = 1; + addiCodeToeBBlock (ebp, newic, ip); + newic->lineno = lineno; + + /* second one */ + if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype)) { + newic = newiCode (SEND, IC_RIGHT (ic), NULL); + newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->next->etype); + } + else + { + newic = newiCode ('=', NULL, IC_RIGHT (ic)); + IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)->next); } - addiCodeToeBBlock (ebp,newic,ip); - newic->lineno = lineno; + addiCodeToeBBlock (ebp, newic, ip); + newic->lineno = lineno; } + else + { + /* compiled as reentrant then push */ + /* push right */ + if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype)) + { + newic = newiCode (SEND, IC_RIGHT (ic), NULL); + newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->next->etype); + } + else + { + newic = newiCode (IPUSH, IC_RIGHT (ic), NULL); + newic->parmPush = 1; + + bytesPushed += getSize(operandType(IC_RIGHT(ic))); + } + addiCodeToeBBlock (ebp, newic, ip); + newic->lineno = lineno; + + /* insert push left */ + if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) + { + newic = newiCode (SEND, IC_LEFT (ic), NULL); + newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype); + } + else + { + newic = newiCode (IPUSH, IC_LEFT (ic), NULL); + newic->parmPush = 1; + + bytesPushed += getSize(operandType(IC_LEFT(ic))); + } + addiCodeToeBBlock (ebp, newic, ip); + newic->lineno = lineno; - /* for the result */ - newic = newiCode(CALL,operandFromSymbol(func),NULL); - IC_RESULT(newic) = IC_RESULT(ic); - addiCodeToeBBlock(ebp,newic,ip); - newic->lineno = lineno; + } + /* for the result */ + newic = newiCode (CALL, operandFromSymbol (func), NULL); + IC_RESULT (newic) = IC_RESULT (ic); + newic->lineno = lineno; + newic->parmBytes+=bytesPushed; // to clear the stack after the call + addiCodeToeBBlock (ebp, newic, ip); } /*-----------------------------------------------------------------*/ /* convertToFcall - converts some operations to fcalls */ /*-----------------------------------------------------------------*/ -static void convertToFcall (eBBlock **ebbs, int count) +static void +convertToFcall (eBBlock ** ebbs, int count) { - int i ; - - /* for all blocks do */ - for (i = 0 ; i < count ; i++ ) { - iCode *ic ; - - /* for all instructions in the block do */ - for (ic = ebbs[i]->sch ; ic ; ic = ic->next ) { - - /* floating point operations are - converted to function calls */ - if ((IS_CONDITIONAL(ic) || - IS_ARITHMETIC_OP(ic) ) && - (IS_FLOAT(operandType(IC_RIGHT(ic))))) { - - cnvToFcall(ic,ebbs[i]); - } - - /* casting is a little different */ - if (ic->op == CAST ) { - if (IS_FLOAT(operandType(IC_RIGHT(ic)))) - cnvFromFloatCast (ic,ebbs[i]); - else - if (IS_FLOAT(operandType(IC_LEFT(ic)))) - cnvToFloatCast (ic,ebbs[i]); + int i; + + /* for all blocks do */ + for (i = 0; i < count; i++) + { + iCode *ic; + + /* for all instructions in the block do */ + for (ic = ebbs[i]->sch; ic; ic = ic->next) + { + + /* floating point operations are + converted to function calls */ + if ((IS_CONDITIONAL (ic) || + IS_ARITHMETIC_OP (ic)) && + (IS_FLOAT (operandType (IC_RIGHT (ic))))) + { + + cnvToFcall (ic, ebbs[i]); } - /* if long / int mult or divide or mod */ - if (ic->op == '*' || ic->op == '/' || ic->op == '%' ) { + /* casting is a little different */ + if (ic->op == CAST) + { + if (IS_FLOAT (operandType (IC_RIGHT (ic)))) + cnvFromFloatCast (ic, ebbs[i]); + else if (IS_FLOAT (operandType (IC_LEFT (ic)))) + cnvToFloatCast (ic, ebbs[i]); + } - link *type = operandType(IC_LEFT(ic)); - if (IS_INTEGRAL(type) && getSize(type) > 1) - convilong (ic,ebbs[i],type,ic->op); + /* if long / int mult or divide or mod */ + if (ic->op == '*' || ic->op == '/' || ic->op == '%') + { + sym_link *leftType = operandType (IC_LEFT (ic)); + + if (IS_INTEGRAL (leftType) && getSize (leftType) > port->support.muldiv) + { + sym_link *rightType = operandType (IC_RIGHT (ic)); + + if (port->hasNativeMulFor != NULL && + port->hasNativeMulFor (ic, leftType, rightType)) + { + /* Leave as native */ + } + else + { + convilong (ic, ebbs[i], leftType, ic->op); + } + } } + + if (ic->op == RRC || ic->op == RLC || ic->op == LEFT_OP || ic->op == RIGHT_OP) + { + sym_link *type = operandType (IC_LEFT (ic)); + + if (IS_INTEGRAL (type) && getSize (type) > port->support.shift && port->support.shift >= 0) + { + convilong (ic, ebbs[i], type, ic->op); + } + } } } } @@ -430,397 +517,408 @@ static void convertToFcall (eBBlock **ebbs, int count) /*-----------------------------------------------------------------*/ /* replaceRegEqv - replace all local variables with their reqv */ /*-----------------------------------------------------------------*/ -static void replaceRegEqv ( eBBlock **ebbs, int count) +static void +replaceRegEqv (eBBlock ** ebbs, int count) { - int i; - - for (i = 0 ; i < count ; i++ ) { - - iCode *ic ; - - for (ic = ebbs[i]->sch ; ic ; ic = ic->next) { - - if (SKIP_IC2(ic)) - continue ; - - if (ic->op == IFX) { - - if (IS_TRUE_SYMOP(IC_COND(ic)) && - OP_REQV(IC_COND(ic))) - IC_COND(ic) = opFromOpWithDU(OP_REQV(IC_COND(ic)), - OP_SYMBOL(IC_COND(ic))->defs, - OP_SYMBOL(IC_COND(ic))->uses); - - continue ; + int i; + + for (i = 0; i < count; i++) + { + + iCode *ic; + + for (ic = ebbs[i]->sch; ic; ic = ic->next) + { + + if (SKIP_IC2 (ic)) + continue; + + if (ic->op == IFX) + { + + if (IS_TRUE_SYMOP (IC_COND (ic)) && + OP_REQV (IC_COND (ic))) + IC_COND (ic) = opFromOpWithDU (OP_REQV (IC_COND (ic)), + OP_SYMBOL (IC_COND (ic))->defs, + OP_SYMBOL (IC_COND (ic))->uses); + + continue; } - if (ic->op == JUMPTABLE) { - if (IS_TRUE_SYMOP(IC_JTCOND(ic)) && - OP_REQV(IC_JTCOND(ic))) - IC_JTCOND(ic) = opFromOpWithDU(OP_REQV(IC_JTCOND(ic)), - OP_SYMBOL(IC_JTCOND(ic))->defs, - OP_SYMBOL(IC_JTCOND(ic))->uses); - continue ; + if (ic->op == JUMPTABLE) + { + if (IS_TRUE_SYMOP (IC_JTCOND (ic)) && + OP_REQV (IC_JTCOND (ic))) + IC_JTCOND (ic) = opFromOpWithDU (OP_REQV (IC_JTCOND (ic)), + OP_SYMBOL (IC_JTCOND (ic))->defs, + OP_SYMBOL (IC_JTCOND (ic))->uses); + continue; } - if (ic->op == RECEIVE) { - if (OP_SYMBOL(IC_RESULT(ic))->addrtaken) - OP_SYMBOL(IC_RESULT(ic))->isspilt = 1; + if (ic->op == RECEIVE) + { + if (OP_SYMBOL (IC_RESULT (ic))->addrtaken) + OP_SYMBOL (IC_RESULT (ic))->isspilt = 1; } - /* general case */ - if (IC_RESULT(ic) && - IS_TRUE_SYMOP(IC_RESULT(ic)) && - OP_REQV(IC_RESULT(ic)) ) { - if (POINTER_SET(ic)) { - IC_RESULT(ic) = opFromOpWithDU(OP_REQV(IC_RESULT(ic)), - OP_SYMBOL(IC_RESULT(ic))->defs, - OP_SYMBOL(IC_RESULT(ic))->uses); - IC_RESULT(ic)->isaddr = 1; - } else - IC_RESULT(ic) = opFromOpWithDU(OP_REQV(IC_RESULT(ic)), - OP_SYMBOL(IC_RESULT(ic))->defs, - OP_SYMBOL(IC_RESULT(ic))->uses); + /* general case */ + if (IC_RESULT (ic) && + IS_TRUE_SYMOP (IC_RESULT (ic)) && + OP_REQV (IC_RESULT (ic))) + { + if (POINTER_SET (ic)) + { + IC_RESULT (ic) = opFromOpWithDU (OP_REQV (IC_RESULT (ic)), + OP_SYMBOL (IC_RESULT (ic))->defs, + OP_SYMBOL (IC_RESULT (ic))->uses); + IC_RESULT (ic)->isaddr = 1; + } + else + IC_RESULT (ic) = opFromOpWithDU (OP_REQV (IC_RESULT (ic)), + OP_SYMBOL (IC_RESULT (ic))->defs, + OP_SYMBOL (IC_RESULT (ic))->uses); } - if (IC_RIGHT(ic) && - IS_TRUE_SYMOP(IC_RIGHT(ic)) && - OP_REQV(IC_RIGHT(ic)) ) { - IC_RIGHT(ic) = opFromOpWithDU(OP_REQV(IC_RIGHT(ic)), - OP_SYMBOL(IC_RIGHT(ic))->defs, - OP_SYMBOL(IC_RIGHT(ic))->uses); - IC_RIGHT(ic)->isaddr = 0; + if (IC_RIGHT (ic) && + IS_TRUE_SYMOP (IC_RIGHT (ic)) && + OP_REQV (IC_RIGHT (ic))) + { + IC_RIGHT (ic) = opFromOpWithDU (OP_REQV (IC_RIGHT (ic)), + OP_SYMBOL (IC_RIGHT (ic))->defs, + OP_SYMBOL (IC_RIGHT (ic))->uses); + IC_RIGHT (ic)->isaddr = 0; } - - if (IC_LEFT(ic) && - IS_TRUE_SYMOP(IC_LEFT(ic)) && - OP_REQV(IC_LEFT(ic)) ) { - IC_LEFT(ic) = opFromOpWithDU(OP_REQV(IC_LEFT(ic)), - OP_SYMBOL(IC_LEFT(ic))->defs, - OP_SYMBOL(IC_LEFT(ic))->uses); - IC_LEFT(ic)->isaddr = 0; + + if (IC_LEFT (ic) && + IS_TRUE_SYMOP (IC_LEFT (ic)) && + OP_REQV (IC_LEFT (ic))) + { + IC_LEFT (ic) = opFromOpWithDU (OP_REQV (IC_LEFT (ic)), + OP_SYMBOL (IC_LEFT (ic))->defs, + OP_SYMBOL (IC_LEFT (ic))->uses); + IC_LEFT (ic)->isaddr = 0; } - } + } } } /*-----------------------------------------------------------------*/ /* killDeadCode - eliminates dead assignments */ /*-----------------------------------------------------------------*/ -int killDeadCode ( eBBlock **ebbs, int count) +int +killDeadCode (eBBlock ** ebbs, int count) { - int change = 1; - int gchange = 0 ; - int i = 0 ; - - - /* basic algorithm :- */ - /* first the exclusion rules :- */ - /* 1. if result is a global or volatile then skip */ - /* 2. if assignment and result is a temp & isaddr then skip */ - /* since this means array & pointer access, will be taken */ - /* care of by alias analysis. */ - /* 3. if the result is used in the remainder of the block skip*/ - /* 4. if this definition does not reach the end of the block */ - /* i.e. the result is not present in the outExprs then KILL*/ - /* 5. if it reaches the end of block & is used by some success*/ - /* or then skip */ - /* else KILL */ - /* this whole process is carried on iteratively till no change */ - while (1) { - - change = 0 ; - /* for all blocks do */ - for ( i = 0 ; i < count ; i++ ) { - iCode *ic ; - - /* for all instructions in the block do */ - for ( ic = ebbs[i]->sch ; ic ; ic = ic->next ) { - int kill, j ; - kill = 0 ; - - if (SKIP_IC(ic) || - ic->op == IFX || - ic->op == RETURN ) - continue ; - - /* if the result is volatile then continue */ - if (IC_RESULT(ic) && isOperandVolatile(IC_RESULT(ic),FALSE)) - continue ; - - /* if the result is a temp & isaddr then skip */ - if (IC_RESULT(ic) && POINTER_SET(ic)) - continue ; - - /* if the result is used in the remainder of the */ - /* block then skip */ - if (usedInRemaining (IC_RESULT(ic),ic->next)) - continue ; - - /* does this definition reach the end of the block - or the usage is zero then we can kill */ - if (! bitVectBitValue(ebbs[i]->outDefs,ic->key)) - kill = 1; /* if not we can kill it */ - else { - /* if this is a global variable or function parameter */ - /* we cannot kill anyway */ - if (isOperandGlobal(IC_RESULT(ic)) || - (OP_SYMBOL(IC_RESULT(ic))->_isparm && - !OP_SYMBOL(IC_RESULT(ic))->ismyparm)) - continue ; - - /* if we are sure there are no usages */ - if (bitVectIsZero(OP_USES(IC_RESULT(ic)))) { - kill = 1 ; - goto kill ; + int change = 1; + int gchange = 0; + int i = 0; + + + /* basic algorithm :- */ + /* first the exclusion rules :- */ + /* 1. if result is a global or volatile then skip */ + /* 2. if assignment and result is a temp & isaddr then skip */ + /* since this means array & pointer access, will be taken */ + /* care of by alias analysis. */ + /* 3. if the result is used in the remainder of the block skip */ + /* 4. if this definition does not reach the end of the block */ + /* i.e. the result is not present in the outExprs then KILL */ + /* 5. if it reaches the end of block & is used by some success */ + /* or then skip */ + /* else KILL */ + /* this whole process is carried on iteratively till no change */ + while (1) + { + + change = 0; + /* for all blocks do */ + for (i = 0; i < count; i++) + { + iCode *ic; + + /* for all instructions in the block do */ + for (ic = ebbs[i]->sch; ic; ic = ic->next) + { + int kill, j; + kill = 0; + + if (SKIP_IC (ic) || + ic->op == IFX || + ic->op == RETURN) + continue; + + /* if the result is volatile then continue */ + if (IC_RESULT (ic) && isOperandVolatile (IC_RESULT (ic), FALSE)) + continue; + + /* if the result is a temp & isaddr then skip */ + if (IC_RESULT (ic) && POINTER_SET (ic)) + continue; + + /* if the result is used in the remainder of the */ + /* block then skip */ + if (usedInRemaining (IC_RESULT (ic), ic->next)) + continue; + + /* does this definition reach the end of the block + or the usage is zero then we can kill */ + if (!bitVectBitValue (ebbs[i]->outDefs, ic->key)) + kill = 1; /* if not we can kill it */ + else + { + /* if this is a global variable or function parameter */ + /* we cannot kill anyway */ + if (isOperandGlobal (IC_RESULT (ic)) || + (OP_SYMBOL (IC_RESULT (ic))->_isparm && + !OP_SYMBOL (IC_RESULT (ic))->ismyparm)) + continue; + + /* if we are sure there are no usages */ + if (bitVectIsZero (OP_USES (IC_RESULT (ic)))) + { + kill = 1; + goto kill; } - /* reset visited flag */ - for(j=0; j < count ; ebbs[j++]->visited = 0); - - /* find out if this definition is alive */ - if ( applyToSet (ebbs[i]->succList, - isDefAlive, - ic)) - continue ; + /* reset visited flag */ + for (j = 0; j < count; ebbs[j++]->visited = 0); + + /* find out if this definition is alive */ + if (applyToSet (ebbs[i]->succList, + isDefAlive, + ic)) + continue; + + kill = 1; + } + + kill: + /* kill this one if required */ + if (kill) + { + change = 1; + gchange++; + /* eliminate this */ + remiCodeFromeBBlock (ebbs[i], ic); + + /* now delete from defUseSet */ + deleteItemIf (&ebbs[i]->outExprs, ifDiCodeIsX, ic); + bitVectUnSetBit (ebbs[i]->outDefs, ic->key); + + /* and defset of the block */ + bitVectUnSetBit (ebbs[i]->defSet, ic->key); + + /* for the left & right remove the usage */ + if (IS_SYMOP (IC_LEFT (ic))) + bitVectUnSetBit (OP_USES (IC_LEFT (ic)), ic->key); - kill = 1; + if (IS_SYMOP (IC_RIGHT (ic))) + bitVectUnSetBit (OP_USES (IC_RIGHT (ic)), ic->key); } - kill : - /* kill this one if required */ - if (kill) { - change = 1; - gchange++ ; - /* eliminate this */ - remiCodeFromeBBlock(ebbs[i],ic); - - /* now delete from defUseSet */ - deleteItemIf (&ebbs[i]->outExprs,ifDiCodeIsX,ic); - bitVectUnSetBit (ebbs[i]->outDefs,ic->key); - - /* and defset of the block */ - bitVectUnSetBit (ebbs[i]->defSet,ic->key); - - /* for the left & right remove the usage */ - if (IS_SYMOP(IC_LEFT(ic))) - bitVectUnSetBit(OP_USES(IC_LEFT(ic)),ic->key); - - if (IS_SYMOP(IC_RIGHT(ic))) - bitVectUnSetBit(OP_USES(IC_RIGHT(ic)),ic->key); - } - - } /* end of all instructions */ - - if (!ebbs[i]->sch && !ebbs[i]->noPath) - disconBBlock(ebbs[i],ebbs,count); - - } /* end of for all blocks */ - - if (!change) - break; - } /* end of while(1) */ - - return gchange ; + } /* end of all instructions */ + + if (!ebbs[i]->sch && !ebbs[i]->noPath) + disconBBlock (ebbs[i], ebbs, count); + + } /* end of for all blocks */ + + if (!change) + break; + } /* end of while(1) */ + + return gchange; } /*-----------------------------------------------------------------*/ /* printCyclomatic - prints the cyclomatic information */ /*-----------------------------------------------------------------*/ -static void printCyclomatic (eBBlock **ebbs, int count) +static void +printCyclomatic (eBBlock ** ebbs, int count) { - int nEdges = elementsInSet(graphEdges); - int i, nNodes =0; + int nEdges = elementsInSet (graphEdges); + int i, nNodes = 0; - for (i = 0 ; i < count ; i++) - nNodes += (! ebbs[i]->noPath); + for (i = 0; i < count; i++) + nNodes += (!ebbs[i]->noPath); - /* print the information */ - werror(I_CYCLOMATIC,currFunc->name,nEdges,nNodes, nEdges - nNodes + 2); + /* print the information */ + werror (I_CYCLOMATIC, currFunc->name, nEdges, nNodes, nEdges - nNodes + 2); } /*-----------------------------------------------------------------*/ -/* canOverlayLocals - returns true if the local variables can overlayed */ +/* discardDeadParamReceives - remove any RECEIVE opcodes which */ +/* refer to dead variables. */ /*-----------------------------------------------------------------*/ -static bool canOverlayLocals (eBBlock **ebbs, int count) +static void +discardDeadParamReceives (eBBlock ** ebbs, int count) { - int i; - /* if staticAuto is in effect or the current function - being compiled is reentrant or the overlay segment - is empty or no overlay option is in effect then */ - if (options.noOverlay || - options.stackAuto || - (currFunc && - (IS_RENT(currFunc->etype) || - IS_ISR(currFunc->etype))) || - elementsInSet(overlay->syms) == 0) - - return FALSE; - - /* otherwise do thru the blocks and see if there - any function calls if found then return false */ - for (i = 0; i < count ; i++ ) { - iCode *ic; - - for (ic = ebbs[i]->sch; ic ; ic = ic->next) - if (ic && ( ic->op == CALL || ic->op == PCALL)) - return FALSE; + int i; + iCode *ic; + iCode dummyIcode; + + for (i = 0; i < count; i++) + { + for (ic = ebbs[i]->sch; ic; ic = ic->next) + { + if (ic->op == RECEIVE) + { + if (IC_RESULT (ic) && OP_SYMBOL (IC_RESULT (ic)) + && !OP_SYMBOL (IC_RESULT (ic))->used) + { +#if 0 + fprintf (stderr, "discarding dead receive for %s\n", + OP_SYMBOL (IC_RESULT (ic))->name); +#endif + dummyIcode.next = ic->next; + remiCodeFromeBBlock (ebbs[i], ic); + ic = &dummyIcode; + } + } + } } - - /* no function calls found return TRUE */ - return TRUE; } - /*-----------------------------------------------------------------*/ /* eBBlockFromiCode - creates extended basic blocks from iCode */ /* will return an array of eBBlock pointers */ /*-----------------------------------------------------------------*/ -eBBlock **eBBlockFromiCode (iCode *ic) -{ - eBBlock **ebbs = NULL ; - int count = 0; - int saveCount = 0 ; - int change = 1; - int lchange = 0 ; - int kchange = 0; - hTab *loops ; - - /* if nothing passed then return nothing */ - if (!ic) - return NULL ; - - count = 0; - eBBNum = 0; - - /* optimize the chain for labels & gotos - this will eliminate redundant labels and - will change jump to jumps by jumps */ - ic = iCodeLabelOptimize (ic); - - /* break it down into basic blocks */ - ebbs = iCodeBreakDown (ic,&count); - saveCount = count ; - - /* compute the control flow */ - computeControlFlow (ebbs,count,0); - - /* dumpraw if asked for */ - if (options.dump_raw) - dumpEbbsToFileExt(".dumpraw0",ebbs,count); - - /* replace the local variables with their - register equivalents : the liveRange computation - along with the register allocation will determine - if it finally stays in the registers */ - replaceRegEqv (ebbs,count); - - /* create loop regions */ - loops = createLoopRegions (ebbs,count); - - /* dumpraw if asked for */ - if (options.dump_raw) - dumpEbbsToFileExt(".dumpraw1",ebbs,count); - - /* do common subexpression elimination for each block */ - change = cseAllBlocks(ebbs,saveCount); - - /* dumpraw if asked for */ - if (options.dump_raw) - dumpEbbsToFileExt(".dumpcse",ebbs,count); - - /* compute the data flow */ - computeDataFlow (ebbs,saveCount); - - /* dumpraw if asked for */ - if (options.dump_raw) - dumpEbbsToFileExt(".dumpdflow",ebbs,count); - - /* global common subexpression elimination */ - if ( optimize.global_cse ) { - change += cseAllBlocks(ebbs,saveCount); - if (options.dump_gcse) - dumpEbbsToFileExt(".dumpgcse",ebbs,saveCount); +eBBlock ** +eBBlockFromiCode (iCode * ic) +{ + eBBlock **ebbs = NULL; + int count = 0; + int saveCount = 0; + int change = 1; + int lchange = 0; + int kchange = 0; + hTab *loops; + + /* if nothing passed then return nothing */ + if (!ic) + return NULL; + + count = 0; + eBBNum = 0; + + /* optimize the chain for labels & gotos + this will eliminate redundant labels and + will change jump to jumps by jumps */ + ic = iCodeLabelOptimize (ic); + + /* break it down into basic blocks */ + ebbs = iCodeBreakDown (ic, &count); + saveCount = count; + + /* compute the control flow */ + computeControlFlow (ebbs, count, 0); + + /* dumpraw if asked for */ + if (options.dump_raw) + dumpEbbsToFileExt (DUMP_RAW0, ebbs, count); + + /* replace the local variables with their + register equivalents : the liveRange computation + along with the register allocation will determine + if it finally stays in the registers */ + replaceRegEqv (ebbs, count); + + /* create loop regions */ + loops = createLoopRegions (ebbs, count); + + /* dumpraw if asked for */ + if (options.dump_raw) + dumpEbbsToFileExt (DUMP_RAW1, ebbs, count); + + /* do common subexpression elimination for each block */ + change = cseAllBlocks (ebbs, saveCount); + + /* dumpraw if asked for */ + if (options.dump_raw) + dumpEbbsToFileExt (DUMP_CSE, ebbs, count); + + /* compute the data flow */ + computeDataFlow (ebbs, saveCount); + + /* dumpraw if asked for */ + if (options.dump_raw) + dumpEbbsToFileExt (DUMP_DFLOW, ebbs, count); + + /* global common subexpression elimination */ + if (optimize.global_cse) + { + change += cseAllBlocks (ebbs, saveCount); + if (options.dump_gcse) + dumpEbbsToFileExt (DUMP_GCSE, ebbs, saveCount); } - /* kill dead code */ - kchange = killDeadCode (ebbs, saveCount); - - if (options.dump_kill) - dumpEbbsToFileExt(".dumpdeadcode",ebbs,count); - - /* do loop optimizations */ - change += (lchange = loopOptimizations (loops,ebbs,count)); - if (options.dump_loop) - dumpEbbsToFileExt(".dumploop",ebbs,count); - - /* recompute the data flow and apply global cse again - if loops optimizations or dead code caused a change: - loops will brings out of the loop which then may be - available for use in the later blocks: dead code - elimination could potentially disconnect some blocks - conditional flow may be efected so we need to apply - subexpression once more */ - if ( lchange || kchange ) { - - computeDataFlow (ebbs,saveCount); - change += cseAllBlocks(ebbs,saveCount); - if (options.dump_loop) - dumpEbbsToFileExt(".dumploopg",ebbs,count); - - /* if loop optimizations caused a change then do - dead code elimination once more : this will - get rid of the extra assignments to the induction - variables created during loop optimizations */ - killDeadCode (ebbs, saveCount); - - if (options.dump_loop) - dumpEbbsToFileExt(".dumploopd",ebbs,count); - - } - - - /* sort it back by block number */ - qsort (ebbs,saveCount,sizeof(eBBlock *),bbNumCompare); - - /* if cyclomatic info requested then print it */ - if (options.cyclomatic) - printCyclomatic(ebbs,saveCount); - - - /* convert operations with support routines - written in C to function calls : Iam doing - this at this point since I want all the - operations to be as they are for optimzations */ - convertToFcall (ebbs,count); - - /* check if the parameters and local variables - of this function can be put in the overlay segment - This check is essentially to see if the function - calls any other functions if yes then we cannot - overlay */ - if (canOverlayLocals(ebbs,count)) - /* if we can then put the parameters & - local variables in the overlay set */ - overlay2Set(); - else - /* otherwise put them into data where - they belong */ - overlay2data(); - - /* compute the live ranges */ - computeLiveRanges (ebbs,count); - - if (options.dump_range) - dumpEbbsToFileExt(".dumprange",ebbs,count); - - /* allocate registers & generate code */ - assignRegisters (ebbs,count); - - /* throw away blocks */ - setToNull ((void **)&graphEdges); - ebbs = NULL ; + /* kill dead code */ + kchange = killDeadCode (ebbs, saveCount); + + if (options.dump_kill) + dumpEbbsToFileExt (DUMP_DEADCODE, ebbs, count); + + /* do loop optimizations */ + change += (lchange = loopOptimizations (loops, ebbs, count)); + if (options.dump_loop) + dumpEbbsToFileExt (DUMP_LOOP, ebbs, count); + + /* recompute the data flow and apply global cse again + if loops optimizations or dead code caused a change: + loops will brings out of the loop which then may be + available for use in the later blocks: dead code + elimination could potentially disconnect some blocks + conditional flow may be efected so we need to apply + subexpression once more */ + if (lchange || kchange) + { + computeDataFlow (ebbs, saveCount); + change += cseAllBlocks (ebbs, saveCount); + if (options.dump_loop) + dumpEbbsToFileExt (DUMP_LOOPG, ebbs, count); + + /* if loop optimizations caused a change then do + dead code elimination once more : this will + get rid of the extra assignments to the induction + variables created during loop optimizations */ + killDeadCode (ebbs, saveCount); + + if (options.dump_loop) + dumpEbbsToFileExt (DUMP_LOOPD, ebbs, count); + } - return NULL; + /* sort it back by block number */ + qsort (ebbs, saveCount, sizeof (eBBlock *), bbNumCompare); + + /* if cyclomatic info requested then print it */ + if (options.cyclomatic) + printCyclomatic (ebbs, saveCount); + + /* convert operations with support routines + written in C to function calls : Iam doing + this at this point since I want all the + operations to be as they are for optimzations */ + convertToFcall (ebbs, count); + + /* compute the live ranges */ + computeLiveRanges (ebbs, count); + + if (options.dump_range) + dumpEbbsToFileExt (DUMP_RANGE, ebbs, count); + + /* Now that we have the live ranges, discard parameter + * receives for unused parameters. + */ + discardDeadParamReceives (ebbs, count); + + /* allocate registers & generate code */ + port->assignRegisters (ebbs, count); + + /* throw away blocks */ + setToNull ((void **) &graphEdges); + ebbs = NULL; + + return NULL; } + + /* (add-hook 'c-mode-hook (lambda () (setq c-basic-offset 4))) */