X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCopt.c;h=05eab6f518d451b39e92f169410e71a509474135;hb=f3946e669d77d841b638d798c3e09429cd3338c6;hp=31d2858df3b21148facb6f5c7dfd22d7cc2fd64e;hpb=d78670def0d8de75614601941b3e69ce937b2714;p=fw%2Fsdcc diff --git a/src/SDCCopt.c b/src/SDCCopt.c index 31d2858d..05eab6f5 100644 --- a/src/SDCCopt.c +++ b/src/SDCCopt.c @@ -148,7 +148,8 @@ cnvToFcall (iCode * ic, eBBlock * ebp) { newic = newiCode (IPUSH, right, NULL); newic->parmPush = 1; - bytesPushed+=4; + //bytesPushed+=4; + bytesPushed += getSize(operandType(right)); } addiCodeToeBBlock (ebp, newic, ip); @@ -164,7 +165,8 @@ cnvToFcall (iCode * ic, eBBlock * ebp) { newic = newiCode (IPUSH, left, NULL); newic->parmPush = 1; - bytesPushed+=4; + //bytesPushed+=4; + bytesPushed += getSize(operandType(left)); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; @@ -174,6 +176,20 @@ cnvToFcall (iCode * ic, eBBlock * ebp) IC_RESULT (newic) = IC_RESULT (ic); newic->lineno = lineno; newic->parmBytes+=bytesPushed; + + 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); } @@ -188,6 +204,7 @@ cnvToFloatCast (iCode * ic, eBBlock * ebp) 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 */ @@ -236,6 +253,7 @@ found: { newic = newiCode (IPUSH, IC_RIGHT (ic), NULL); newic->parmPush = 1; + bytesPushed += getSize(operandType(IC_RIGHT(ic))); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = linenno; @@ -245,9 +263,23 @@ found: /* make the call */ newic = newiCode (CALL, operandFromSymbol (func), NULL); IC_RESULT (newic) = IC_RESULT (ic); + newic->parmBytes+=bytesPushed; + + 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; - } /*-----------------------------------------------------------------*/ @@ -261,6 +293,7 @@ cnvFromFloatCast (iCode * ic, eBBlock * ebp) 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 */ @@ -310,6 +343,7 @@ found: { newic = newiCode (IPUSH, IC_RIGHT (ic), NULL); newic->parmPush = 1; + bytesPushed += getSize(operandType(IC_RIGHT(ic))); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; @@ -319,11 +353,27 @@ found: /* make the call */ newic = newiCode (CALL, operandFromSymbol (func), NULL); IC_RESULT (newic) = IC_RESULT (ic); + newic->parmBytes+=bytesPushed; + + 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 */ /*-----------------------------------------------------------------*/ @@ -338,8 +388,34 @@ convilong (iCode * ic, eBBlock * ebp, sym_link * type, int op) int su; int bytesPushed=0; - remiCodeFromeBBlock (ebp, ic); - + // 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++) { @@ -441,6 +517,20 @@ found: IC_RESULT (newic) = IC_RESULT (ic); newic->lineno = lineno; newic->parmBytes+=bytesPushed; // to clear the stack after the call + + 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); } @@ -514,6 +604,34 @@ convertToFcall (eBBlock ** ebbs, int count) } } +/*-----------------------------------------------------------------*/ +/* isLocalWithoutDef - return 1 if sym might be used without a */ +/* defining iCode */ +/*-----------------------------------------------------------------*/ +static int +isLocalWithoutDef (symbol * sym) +{ + if (!sym->level) + return 0; + + if (IS_STATIC (sym->etype)) + 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 */ /*-----------------------------------------------------------------*/ @@ -522,6 +640,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++) { @@ -535,7 +659,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)), @@ -545,8 +679,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)), @@ -579,6 +725,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))) @@ -589,6 +746,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))) @@ -643,9 +811,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; @@ -653,6 +828,9 @@ 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)) + continue; /* if the result is used in the remainder of the */ /* block then skip */ @@ -689,18 +867,32 @@ killDeadCode (eBBlock ** ebbs, int count) continue; kill = 1; - } + } kill: /* kill this one if required */ if (kill) { - printf ("kill ic %d\n", ic->key); + bool volLeft = IS_SYMOP (IC_LEFT (ic)) + && isOperandVolatile (IC_LEFT (ic), FALSE); + bool volRight = IS_SYMOP (IC_RIGHT (ic)) + && isOperandVolatile (IC_RIGHT (ic), 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; + } + 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); @@ -708,12 +900,33 @@ 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); + /* 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); - if (IS_SYMOP (IC_RIGHT (ic))) - bitVectUnSetBit (OP_USES (IC_RIGHT (ic)), 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 */ @@ -810,6 +1023,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); @@ -847,14 +1066,14 @@ eBBlockFromiCode (iCode * ic) /* global common subexpression elimination */ if (optimize.global_cse) { - change += cseAllBlocks (ebbs, saveCount, TRUE); + change += cseAllBlocks (ebbs, saveCount, FALSE); if (options.dump_gcse) dumpEbbsToFileExt (DUMP_GCSE, ebbs, saveCount); } else { // compute the dataflow only - assert(cseAllBlocks (ebbs, saveCount, FALSE)==0); + assert(cseAllBlocks (ebbs, saveCount, TRUE)==0); } /* kill dead code */ kchange = killDeadCode (ebbs, saveCount); @@ -877,7 +1096,7 @@ eBBlockFromiCode (iCode * ic) if (lchange || kchange) { computeDataFlow (ebbs, saveCount); - change += cseAllBlocks (ebbs, saveCount, TRUE); + change += cseAllBlocks (ebbs, saveCount, FALSE); if (options.dump_loop) dumpEbbsToFileExt (DUMP_LOOPG, ebbs, count); @@ -898,14 +1117,17 @@ eBBlockFromiCode (iCode * ic) if (!options.lessPedantic) { // this is a good place to check missing return values if (currFunc) { - if (!IS_VOID(currFunc->etype)) { + // 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) { - werror (W_VOID_FUNC, currFunc->name); + werrorfl (bp->ech->filename, bp->ech->lineno, + W_VOID_FUNC, currFunc->name); } } } @@ -937,11 +1159,9 @@ eBBlockFromiCode (iCode * ic) port->assignRegisters (ebbs, count); /* throw away blocks */ - setToNull ((void **) &graphEdges); + setToNull ((void *) &graphEdges); ebbs = NULL; - currFunc=NULL; - return NULL; }