X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCopt.c;h=94ee6e187b5d0231dc418575b510578387eb20cd;hb=0625cd3d1d5e43a2d9d437b7b8f690edbd8c2778;hp=0a21e032896b8ec4a8077b12df842a9af8e49d55;hpb=677acf94ea50645d09ce1f764aba4679de762bd8;p=fw%2Fsdcc diff --git a/src/SDCCopt.c b/src/SDCCopt.c index 0a21e032..94ee6e18 100644 --- a/src/SDCCopt.c +++ b/src/SDCCopt.c @@ -58,6 +58,7 @@ cnvToFcall (iCode * ic, eBBlock * ebp) operand *right; symbol *func = NULL; int lineno = ic->lineno; + int bytesPushed=0; ip = ic->next; /* insertion point */ /* remove it from the iCode */ @@ -105,28 +106,30 @@ cnvToFcall (iCode * ic, eBBlock * ebp) { /* first one */ - if (IS_REGPARM (func->args->etype)) + 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); + IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; /* second one */ - if (IS_REGPARM (func->args->next->etype)) + if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype)) { - newic = newiCode (SEND, IC_LEFT (ic), NULL); + 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->next); + IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)->next); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; @@ -136,28 +139,34 @@ cnvToFcall (iCode * ic, eBBlock * ebp) { /* push right */ - if (IS_REGPARM (func->args->next->etype)) + if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype)) { newic = newiCode (SEND, right, NULL); + newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->next->etype); } else { newic = newiCode (IPUSH, right, NULL); newic->parmPush = 1; + //bytesPushed+=4; + bytesPushed += getSize(operandType(right)); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; /* insert push left */ - if (IS_REGPARM (func->args->etype)) + 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; + bytesPushed += getSize(operandType(left)); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; @@ -165,8 +174,26 @@ cnvToFcall (iCode * ic, eBBlock * ebp) /* insert the call */ newic = newiCode (CALL, operandFromSymbol (func), NULL); IC_RESULT (newic) = IC_RESULT (ic); - addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; + newic->parmBytes+=bytesPushed; + ebp->hasFcall = 1; + if (currFunc) + FUNC_HASFCALL (currFunc->type) = 1; + + if(TARGET_IS_PIC16) { + /* normally these functions aren't marked external, so we can use their + * _extern field to marked as already added to symbol table */ + + if(!SPEC_EXTR(func->etype)) { + memmap *seg = SPEC_OCLS(OP_SYMBOL(IC_LEFT(newic))->etype); + + SPEC_EXTR(func->etype) = 1; + seg = SPEC_OCLS( func->etype ); + addSet(&seg->syms, func); + } + } + + addiCodeToeBBlock (ebp, newic, ip); } /*-----------------------------------------------------------------*/ @@ -176,10 +203,11 @@ static void cnvToFloatCast (iCode * ic, eBBlock * ebp) { iCode *ip, *newic; - symbol *func; + symbol *func = NULL; sym_link *type = operandType (IC_RIGHT (ic)); int linenno = ic->lineno; int bwd, su; + int bytesPushed=0; ip = ic->next; /* remove it from the iCode */ @@ -189,7 +217,7 @@ cnvToFloatCast (iCode * ic, eBBlock * ebp) { for (su = 0; su < 2; su++) { - if (checkType (type, __multypes[bwd][su]) == 1) + if (compareType (type, __multypes[bwd][su]) == 1) { func = __conv[0][bwd][su]; goto found; @@ -203,12 +231,15 @@ found: if (!options.float_rent) { /* first one */ - if (IS_REGPARM (func->args->etype)) - newic = newiCode (SEND, IC_RIGHT (ic), NULL); + 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); + IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = linenno; @@ -217,12 +248,15 @@ found: else { /* push the left */ - if (IS_REGPARM (func->args->etype)) - newic = newiCode (SEND, IC_RIGHT (ic), NULL); + 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; + bytesPushed += getSize(operandType(IC_RIGHT(ic))); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = linenno; @@ -232,9 +266,26 @@ found: /* make the call */ newic = newiCode (CALL, operandFromSymbol (func), NULL); IC_RESULT (newic) = IC_RESULT (ic); + newic->parmBytes+=bytesPushed; + ebp->hasFcall = 1; + if (currFunc) + FUNC_HASFCALL (currFunc->type) = 1; + + if(TARGET_IS_PIC16) { + /* normally these functions aren't marked external, so we can use their + * _extern field to marked as already added to symbol table */ + + if(!SPEC_EXTR(func->etype)) { + memmap *seg = SPEC_OCLS(OP_SYMBOL(IC_LEFT(newic))->etype); + + SPEC_EXTR(func->etype) = 1; + seg = SPEC_OCLS( func->etype ); + addSet(&seg->syms, func); + } + } + addiCodeToeBBlock (ebp, newic, ip); newic->lineno = linenno; - } /*-----------------------------------------------------------------*/ @@ -244,10 +295,11 @@ static void cnvFromFloatCast (iCode * ic, eBBlock * ebp) { iCode *ip, *newic; - symbol *func; + symbol *func = NULL; sym_link *type = operandType (IC_LEFT (ic)); int lineno = ic->lineno; int bwd, su; + int bytesPushed=0; ip = ic->next; /* remove it from the iCode */ @@ -258,7 +310,7 @@ cnvFromFloatCast (iCode * ic, eBBlock * ebp) { for (su = 0; su < 2; su++) { - if (checkType (type, __multypes[bwd][su]) == 1) + if (compareType (type, __multypes[bwd][su]) == 1) { func = __conv[1][bwd][su]; goto found; @@ -272,12 +324,14 @@ found: if (!options.float_rent) { /* first one */ - if (IS_REGPARM (func->args->etype)) - newic = newiCode (SEND, IC_RIGHT (ic), NULL); + 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); + IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; @@ -287,12 +341,15 @@ found: { /* push the left */ - if (IS_REGPARM (func->args->etype)) - newic = newiCode (SEND, IC_RIGHT (ic), NULL); + 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; + bytesPushed += getSize(operandType(IC_RIGHT(ic))); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; @@ -302,11 +359,30 @@ found: /* make the call */ newic = newiCode (CALL, operandFromSymbol (func), NULL); IC_RESULT (newic) = IC_RESULT (ic); + newic->parmBytes+=bytesPushed; + ebp->hasFcall = 1; + if (currFunc) + FUNC_HASFCALL (currFunc->type) = 1; + + if(TARGET_IS_PIC16) { + /* normally these functions aren't marked external, so we can use their + * _extern field to marked as already added to symbol table */ + + if(!SPEC_EXTR(func->etype)) { + memmap *seg = SPEC_OCLS(OP_SYMBOL(IC_LEFT(newic))->etype); + + SPEC_EXTR(func->etype) = 1; + seg = SPEC_OCLS( func->etype ); + addSet(&seg->syms, func); + } + } + addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; - } +extern operand *geniCodeRValue (operand *, bool); + /*-----------------------------------------------------------------*/ /* convilong - converts int or long mults or divs to fcalls */ /*-----------------------------------------------------------------*/ @@ -319,14 +395,42 @@ convilong (iCode * ic, eBBlock * ebp, sym_link * type, int op) int lineno = ic->lineno; int bwd; int su; - remiCodeFromeBBlock (ebp, ic); - + int bytesPushed=0; + + // Easy special case which avoids function call: modulo by a literal power + // of two can be replaced by a bitwise AND. + if (op == '%' && isOperandLiteral(IC_RIGHT(ic))) + { + unsigned litVal = (unsigned)(operandLitValue(IC_RIGHT(ic))); + + // See if literal value is a power of 2. + while (litVal && !(litVal & 1)) + { + litVal >>= 1; + } + if (litVal) + { + // discard first high bit set. + litVal >>= 1; + } + + if (!litVal) + { + ic->op = BITWISEAND; + IC_RIGHT(ic) = operandFromLit(operandLitValue(IC_RIGHT(ic)) - 1); + return; + } + } + + remiCodeFromeBBlock (ebp, ic); + + /* depending on the type */ for (bwd = 0; bwd < 3; bwd++) { for (su = 0; su < 2; su++) { - if (checkType (type, __multypes[bwd][su]) == 1) + if (compareType (type, __multypes[bwd][su]) == 1) { if (op == '*') func = __muldiv[0][bwd][su]; @@ -334,6 +438,14 @@ convilong (iCode * ic, eBBlock * ebp, sym_link * type, int 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; @@ -346,51 +458,63 @@ found: if (!options.intlong_rent) { /* first one */ - if (IS_REGPARM (func->args->etype)) - newic = newiCode (SEND, IC_LEFT (ic), NULL); + 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); + IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; /* second one */ - if (IS_REGPARM (func->args->next->etype)) - newic = newiCode (SEND, IC_RIGHT (ic), NULL); + 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->next); + IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)->next); } 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); + 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->etype)) - newic = newiCode (SEND, IC_LEFT (ic), NULL); + 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; @@ -400,9 +524,26 @@ found: /* for the result */ newic = newiCode (CALL, operandFromSymbol (func), NULL); IC_RESULT (newic) = IC_RESULT (ic); - addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; + newic->parmBytes+=bytesPushed; // to clear the stack after the call + ebp->hasFcall = 1; + if (currFunc) + FUNC_HASFCALL (currFunc->type) = 1; + + if(TARGET_IS_PIC16) { + /* normally these functions aren't marked external, so we can use their + * _extern field to marked as already added to symbol table */ + + if(!SPEC_EXTR(func->etype)) { + memmap *seg = SPEC_OCLS(OP_SYMBOL(IC_LEFT(newic))->etype); + + SPEC_EXTR(func->etype) = 1; + seg = SPEC_OCLS( func->etype ); + addSet(&seg->syms, func); + } + } + addiCodeToeBBlock (ebp, newic, ip); } /*-----------------------------------------------------------------*/ @@ -444,15 +585,62 @@ convertToFcall (eBBlock ** ebbs, int count) /* if long / int mult or divide or mod */ if (ic->op == '*' || ic->op == '/' || ic->op == '%') { - - sym_link *type = operandType (IC_LEFT (ic)); - if (IS_INTEGRAL (type) && getSize (type) > port->muldiv.native_below) - convilong (ic, ebbs[i], type, 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); + } + } } } } +/*-----------------------------------------------------------------*/ +/* isLocalWithoutDef - return 1 if sym might be used without a */ +/* defining iCode */ +/*-----------------------------------------------------------------*/ +static int +isLocalWithoutDef (symbol * sym) +{ + if (!IS_AUTO (sym)) + return 0; + + if (IS_VOLATILE (sym->type)) + return 0; + + if (sym->_isparm) + return 0; + + if (IS_AGGREGATE (sym->type)) + return 0; + + if (sym->addrtaken) + return 0; + + return !sym->defs; +} + /*-----------------------------------------------------------------*/ /* replaceRegEqv - replace all local variables with their reqv */ /*-----------------------------------------------------------------*/ @@ -461,6 +649,12 @@ replaceRegEqv (eBBlock ** ebbs, int count) { int i; + /* Update the symbols' def bitvector so we know if there is */ + /* a defining iCode or not. Only replace a local variable */ + /* with its register equivalent if there is a defining iCode; */ + /* otherwise, the port's register allocater may choke. */ + cseAllBlocks (ebbs, count, TRUE); + for (i = 0; i < count; i++) { @@ -474,7 +668,17 @@ replaceRegEqv (eBBlock ** ebbs, int count) if (ic->op == IFX) { - + if (IC_COND (ic) && + IS_TRUE_SYMOP (IC_COND (ic)) && + isLocalWithoutDef (OP_SYMBOL (IC_COND (ic)))) + { + werrorfl (ic->filename, ic->lineno, + W_LOCAL_NOINIT, + OP_SYMBOL (IC_COND (ic))->name); + OP_REQV (IC_COND (ic)) = NULL; + OP_SYMBOL (IC_COND (ic))->allocreq = 1; + } + if (IS_TRUE_SYMOP (IC_COND (ic)) && OP_REQV (IC_COND (ic))) IC_COND (ic) = opFromOpWithDU (OP_REQV (IC_COND (ic)), @@ -484,8 +688,20 @@ replaceRegEqv (eBBlock ** ebbs, int count) continue; } + if (ic->op == JUMPTABLE) { + if (IC_JTCOND (ic) && + IS_TRUE_SYMOP (IC_JTCOND (ic)) && + isLocalWithoutDef (OP_SYMBOL (IC_JTCOND (ic)))) + { + werrorfl (ic->filename, ic->lineno, + W_LOCAL_NOINIT, + OP_SYMBOL (IC_JTCOND (ic))->name); + OP_REQV (IC_JTCOND (ic)) = NULL; + OP_SYMBOL (IC_JTCOND (ic))->allocreq = 1; + } + if (IS_TRUE_SYMOP (IC_JTCOND (ic)) && OP_REQV (IC_JTCOND (ic))) IC_JTCOND (ic) = opFromOpWithDU (OP_REQV (IC_JTCOND (ic)), @@ -518,6 +734,17 @@ replaceRegEqv (eBBlock ** ebbs, int count) OP_SYMBOL (IC_RESULT (ic))->uses); } + if (IC_RIGHT (ic) && + IS_TRUE_SYMOP (IC_RIGHT (ic)) && + isLocalWithoutDef (OP_SYMBOL (IC_RIGHT (ic)))) + { + werrorfl (ic->filename, ic->lineno, + W_LOCAL_NOINIT, + OP_SYMBOL (IC_RIGHT (ic))->name); + OP_REQV (IC_RIGHT (ic)) = NULL; + OP_SYMBOL (IC_RIGHT (ic))->allocreq = 1; + } + if (IC_RIGHT (ic) && IS_TRUE_SYMOP (IC_RIGHT (ic)) && OP_REQV (IC_RIGHT (ic))) @@ -528,6 +755,17 @@ replaceRegEqv (eBBlock ** ebbs, int count) IC_RIGHT (ic)->isaddr = 0; } + if (IC_LEFT (ic) && + IS_TRUE_SYMOP (IC_LEFT (ic)) && + isLocalWithoutDef (OP_SYMBOL (IC_LEFT (ic)))) + { + werrorfl (ic->filename, ic->lineno, + W_LOCAL_NOINIT, + OP_SYMBOL (IC_LEFT (ic))->name); + OP_REQV (IC_LEFT (ic)) = NULL; + OP_SYMBOL (IC_LEFT (ic))->allocreq = 1; + } + if (IC_LEFT (ic) && IS_TRUE_SYMOP (IC_LEFT (ic)) && OP_REQV (IC_LEFT (ic))) @@ -541,6 +779,51 @@ replaceRegEqv (eBBlock ** ebbs, int count) } } +/*-----------------------------------------------------------------*/ +/* findReqv - search for a register equivalent */ +/*-----------------------------------------------------------------*/ +operand * +findReqv (symbol * prereqv, eBBlock ** ebbs, int count) +{ + int i; + iCode * ic; + + /* for all blocks do */ + for (i=0; isch; ic; ic = ic->next) + { + if (ic->op == IFX) + { + if (IS_ITEMP (IC_COND (ic)) + && OP_SYMBOL (IC_COND (ic))->prereqv == prereqv) + return IC_COND (ic); + } + else if (ic->op == JUMPTABLE) + { + if (IS_ITEMP (IC_JTCOND (ic)) + && OP_SYMBOL (IC_JTCOND (ic))->prereqv == prereqv) + return IC_JTCOND (ic); + } + else + { + if (IS_ITEMP (IC_LEFT (ic)) + && OP_SYMBOL (IC_LEFT (ic))->prereqv == prereqv) + return IC_LEFT (ic); + if (IS_ITEMP (IC_RIGHT (ic)) + && OP_SYMBOL (IC_RIGHT (ic))->prereqv == prereqv) + return IC_RIGHT (ic); + if (IS_ITEMP (IC_RESULT (ic)) + && OP_SYMBOL (IC_RESULT (ic))->prereqv == prereqv) + return IC_RESULT (ic); + } + } + } + + return NULL; +} + /*-----------------------------------------------------------------*/ /* killDeadCode - eliminates dead assignments */ /*-----------------------------------------------------------------*/ @@ -582,9 +865,16 @@ killDeadCode (eBBlock ** ebbs, int count) if (SKIP_IC (ic) || ic->op == IFX || - ic->op == RETURN) + ic->op == RETURN || + ic->op == DUMMY_READ_VOLATILE || + ic->op == CRITICAL || + ic->op == ENDCRITICAL) continue; + /* Since both IFX & JUMPTABLE (in SKIP_IC) have been tested for */ + /* it is now safe to assume IC_LEFT, IC_RIGHT, & IC_RESULT are */ + /* valid. */ + /* if the result is volatile then continue */ if (IC_RESULT (ic) && isOperandVolatile (IC_RESULT (ic), FALSE)) continue; @@ -592,6 +882,10 @@ killDeadCode (eBBlock ** ebbs, int count) /* if the result is a temp & isaddr then skip */ if (IC_RESULT (ic) && POINTER_SET (ic)) continue; + + if (POINTER_GET (ic) && IS_VOLATILE (operandType (IC_LEFT (ic))->next) + && !SPIL_LOC (IC_RESULT (ic))) + continue; /* if the result is used in the remainder of the */ /* block then skip */ @@ -628,17 +922,45 @@ killDeadCode (eBBlock ** ebbs, int count) continue; kill = 1; - } + } kill: /* kill this one if required */ if (kill) { + bool volLeft = IS_SYMOP (IC_LEFT (ic)) + && isOperandVolatile (IC_LEFT (ic), FALSE); + bool volRight = IS_SYMOP (IC_RIGHT (ic)) + && isOperandVolatile (IC_RIGHT (ic), FALSE); + + /* a dead address-of operation should die, even if volatile */ + if (ic->op == ADDRESS_OF) + volLeft = FALSE; + + if (ic->next && ic->seqPoint == ic->next->seqPoint + && (ic->next->op == '+' || ic->next->op == '-')) + { + if (isOperandEqual (IC_LEFT(ic), IC_LEFT(ic->next)) + || isOperandEqual (IC_LEFT(ic), IC_RIGHT(ic->next))) + volLeft = FALSE; + if (isOperandEqual (IC_RIGHT(ic), IC_LEFT(ic->next)) + || isOperandEqual (IC_RIGHT(ic), IC_RIGHT(ic->next))) + volRight = FALSE; + } + + if (POINTER_GET (ic) && IS_VOLATILE (operandType (IC_LEFT (ic))->next)) + { + if (SPIL_LOC (IC_RESULT (ic))) + { + IC_RESULT (ic) = newiTempFromOp (IC_RESULT (ic)); + SPIL_LOC (IC_RESULT (ic)) = NULL; + } + continue; + } + 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); @@ -646,12 +968,56 @@ killDeadCode (eBBlock ** ebbs, int count) /* 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 this is the last of a register equivalent, */ + /* look for a successor register equivalent. */ + bitVectUnSetBit (OP_DEFS (IC_RESULT (ic)), ic->key); + if (IS_ITEMP (IC_RESULT (ic)) + && OP_SYMBOL (IC_RESULT (ic))->isreqv + && bitVectIsZero (OP_DEFS (IC_RESULT (ic)))) + { + symbol * resultsym = OP_SYMBOL (IC_RESULT (ic)); + symbol * prereqv = resultsym->prereqv; + + if (OP_SYMBOL (prereqv->reqv) == resultsym) + { + operand * newreqv; + + IC_RESULT (ic) = NULL; + newreqv = findReqv (prereqv, ebbs, count); + if (newreqv) + { + prereqv->reqv = newreqv; + } + } + } + + /* delete the result */ + IC_RESULT (ic) = NULL; + + if (volLeft || volRight) + { + /* something is volatile, so keep the iCode */ + /* and change the operator instead */ + ic->op = DUMMY_READ_VOLATILE; + + /* keep only the volatile operands */ + if (!volLeft) + IC_LEFT (ic) = NULL; + if (!volRight) + IC_RIGHT (ic) = NULL; + } + else + { + /* nothing is volatile, eliminate the iCode */ + remiCodeFromeBBlock (ebbs[i], ic); + + /* 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); + if (IS_SYMOP (IC_RIGHT (ic))) + bitVectUnSetBit (OP_USES (IC_RIGHT (ic)), ic->key); + } } } /* end of all instructions */ @@ -717,6 +1083,76 @@ discardDeadParamReceives (eBBlock ** ebbs, int count) } } +/*-----------------------------------------------------------------*/ +/* optimizeCastCast - remove unneeded intermediate casts. */ +/* Integer promotion may cast (un)signed char to int and then */ +/* recast the int to (un)signed long. If the signedness of the */ +/* char and long are the same, the cast can be safely performed in */ +/* a single step. */ +/*-----------------------------------------------------------------*/ +static void +optimizeCastCast (eBBlock ** ebbs, int count) +{ + int i; + iCode *ic; + iCode *uic; + sym_link * type1; + sym_link * type2; + sym_link * type3; + symbol * sym; + + for (i = 0; i < count; i++) + { + for (ic = ebbs[i]->sch; ic; ic = ic->next) + { + + if (ic->op == CAST && IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic))) + { + type1 = operandType (IC_RIGHT (ic)); + type2 = operandType (IC_RESULT (ic)); + + /* Look only for a cast from an integer type to an */ + /* integer type that has no loss of bits */ + if (!IS_INTEGRAL (type1) || !IS_INTEGRAL (type2)) + continue; + if (getSize (type2) < getSize (type1)) + continue; + + /* There must be only one use of this first result */ + if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) != 1) + continue; + + /* This use must be a second cast */ + uic = hTabItemWithKey (iCodehTab, + bitVectFirstBit (OP_USES (IC_RESULT (ic)))); + if (!uic || uic->op != CAST) + continue; + + /* It must be a cast to another integer type that */ + /* has no loss of bits */ + type3 = operandType (IC_RESULT (uic)); + if (!IS_INTEGRAL (type3)) + continue; + if (getSize (type3) < getSize (type2)) + continue; + + /* The signedness between the first and last types */ + /* must match */ + if (SPEC_USIGN (type3) != SPEC_USIGN (type1)) + continue; + + /* Change the first cast to a simple assignment and */ + /* let the second cast do all the work */ + ic->op = '='; + IC_LEFT (ic) = NULL; + sym = OP_SYMBOL (IC_RESULT (ic)); + sym->type = copyLinkChain (type1); + sym->etype = getSpec (sym->type); + } + } + } +} + /*-----------------------------------------------------------------*/ /* eBBlockFromiCode - creates extended basic blocks from iCode */ /* will return an array of eBBlock pointers */ @@ -748,6 +1184,12 @@ eBBlockFromiCode (iCode * ic) ebbs = iCodeBreakDown (ic, &count); saveCount = count; + /* hash the iCode keys so that we can quickly index */ + /* them in the rest of the optimization steps */ + setToNull ((void *) &iCodehTab); + iCodehTab = newHashTable (iCodeKey); + hashiCodeKeys (ebbs, count); + /* compute the control flow */ computeControlFlow (ebbs, count, 0); @@ -768,8 +1210,10 @@ eBBlockFromiCode (iCode * ic) if (options.dump_raw) dumpEbbsToFileExt (DUMP_RAW1, ebbs, count); + optimizeCastCast (ebbs, saveCount); + /* do common subexpression elimination for each block */ - change = cseAllBlocks (ebbs, saveCount); + change = cseAllBlocks (ebbs, saveCount, FALSE); /* dumpraw if asked for */ if (options.dump_raw) @@ -785,10 +1229,15 @@ eBBlockFromiCode (iCode * ic) /* global common subexpression elimination */ if (optimize.global_cse) { - change += cseAllBlocks (ebbs, saveCount); + change += cseAllBlocks (ebbs, saveCount, FALSE); if (options.dump_gcse) dumpEbbsToFileExt (DUMP_GCSE, ebbs, saveCount); } + else + { + // compute the dataflow only + assert(cseAllBlocks (ebbs, saveCount, TRUE)==0); + } /* kill dead code */ kchange = killDeadCode (ebbs, saveCount); @@ -809,9 +1258,8 @@ eBBlockFromiCode (iCode * ic) subexpression once more */ if (lchange || kchange) { - computeDataFlow (ebbs, saveCount); - change += cseAllBlocks (ebbs, saveCount); + change += cseAllBlocks (ebbs, saveCount, FALSE); if (options.dump_loop) dumpEbbsToFileExt (DUMP_LOOPG, ebbs, count); @@ -826,22 +1274,39 @@ eBBlockFromiCode (iCode * ic) } - /* sort it back by block number */ qsort (ebbs, saveCount, sizeof (eBBlock *), bbNumCompare); + if (!options.lessPedantic) { + // this is a good place to check missing return values + if (currFunc) { + // the user is on his own with naked functions... + if (!IS_VOID(currFunc->etype) + && !FUNC_ISNAKED(currFunc->type)) { + eBBlock *bp; + // make sure all predecessors of the last block end in a return + for (bp=setFirstItem(ebbs[saveCount-1]->predList); + bp; + bp=setNextItem(ebbs[saveCount-1]->predList)) { + if (bp->ech->op != RETURN) { + werrorfl (bp->ech->filename, bp->ech->lineno, + W_VOID_FUNC, currFunc->name); + } + } + } + } + } + /* 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); @@ -857,10 +1322,9 @@ eBBlockFromiCode (iCode * ic) port->assignRegisters (ebbs, count); /* throw away blocks */ - setToNull ((void **) &graphEdges); + setToNull ((void *) &graphEdges); ebbs = NULL; - - + return NULL; }