X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCopt.c;h=bf6d4cbee4fc01a534b652222eccb918ace0331a;hb=11979e848b68c5b93ff18a4c45d97fcd8afe59f4;hp=e76e30f39cd97ae71a17c880b6970b9eb28030d3;hpb=30249085d67be1d695ad91e97ad2f571352fed36;p=fw%2Fsdcc diff --git a/src/SDCCopt.c b/src/SDCCopt.c index e76e30f3..bf6d4cbe 100644 --- a/src/SDCCopt.c +++ b/src/SDCCopt.c @@ -67,39 +67,77 @@ cnvToFcall (iCode * ic, eBBlock * ebp) 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; - } + if(IS_FLOAT(operandType( 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; + } + } else + if(IS_FIXED16X16 (operandType (IC_RIGHT(ic)))) { + switch (ic->op) + { + case '+': + func = __fps16x16_add; + break; + case '-': + func = __fps16x16_sub; + break; + case '/': + func = __fps16x16_div; + break; + case '*': + func = __fps16x16_mul; + break; + case EQ_OP: + func = __fps16x16_eq; + break; + case NE_OP: + func = __fps16x16_neq; + break; + case '<': + func = __fps16x16_lt; + break; + case '>': + func = __fps16x16_gt; + break; + case LE_OP: + func = __fps16x16_lteq; + break; + case GE_OP: + func = __fps16x16_gteq; + break; + } + } + /* if float support routines NOT compiled as reentrant */ if (!options.float_rent) @@ -224,6 +262,104 @@ cnvToFloatCast (iCode * ic, eBBlock * ebp) } } } + + if(compareType (type, fixed16x16Type) == 1) { + func = __fp16x16conv[0][3][0]; + 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 = 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; + bytesPushed += getSize(operandType(IC_RIGHT(ic))); + } + addiCodeToeBBlock (ebp, newic, ip); + newic->lineno = linenno; + + } + + /* 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; +} + +/*----------------------------------------------------------------------*/ +/* cnvToFixed16x16Cast - converts casts to fixed16x16 to function calls */ +/*----------------------------------------------------------------------*/ +static void +cnvToFixed16x16Cast (iCode * ic, eBBlock * ebp) +{ + iCode *ip, *newic; + 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 */ + 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 = __fp16x16conv[0][bwd][su]; + goto found; + } + } + } assert (0); found: @@ -381,6 +517,106 @@ found: newic->lineno = lineno; } +/*--------------------------------------------------------------------------*/ +/* cnvFromFixed16x16Cast - converts casts from fixed16x16 to function calls */ +/*--------------------------------------------------------------------------*/ +static void +cnvFromFixed16x16Cast (iCode * ic, eBBlock * ebp) +{ + iCode *ip, *newic; + 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 */ + 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 = __fp16x16conv[1][bwd][su]; + goto found; + } + } + } + + if (compareType (type, floatType) == 1) + { + func = __fp16x16conv[1][3][0]; + 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; + + } + 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; + bytesPushed += getSize(operandType(IC_RIGHT(ic))); + } + addiCodeToeBBlock (ebp, newic, ip); + newic->lineno = lineno; + + } + + /* 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); /*-----------------------------------------------------------------*/ @@ -397,34 +633,8 @@ convilong (iCode * ic, eBBlock * ebp, sym_link * type, int op) int su; 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++) { @@ -567,7 +777,8 @@ convertToFcall (eBBlock ** ebbs, int count) converted to function calls */ if ((IS_CONDITIONAL (ic) || IS_ARITHMETIC_OP (ic)) && - (IS_FLOAT (operandType (IC_RIGHT (ic))))) + (IS_FLOAT (operandType (IC_RIGHT (ic))) + || IS_FIXED( operandType (IC_RIGHT (ic))))) { cnvToFcall (ic, ebbs[i]); @@ -580,8 +791,46 @@ convertToFcall (eBBlock ** ebbs, int count) cnvFromFloatCast (ic, ebbs[i]); else if (IS_FLOAT (operandType (IC_LEFT (ic)))) cnvToFloatCast (ic, ebbs[i]); + if (IS_FIXED16X16 (operandType (IC_RIGHT (ic)))) + cnvFromFixed16x16Cast (ic, ebbs[i]); + else if (IS_FIXED16X16 (operandType (IC_LEFT (ic)))) + cnvToFixed16x16Cast (ic, ebbs[i]); } + // Easy special case which avoids function call: modulo by a literal power + // of two can be replaced by a bitwise AND. + if (ic->op == '%' && isOperandLiteral(IC_RIGHT(ic)) && + IS_UNSIGNED(operandType(IC_LEFT(ic)))) + { + unsigned litVal = fabs(operandLitValue(IC_RIGHT(ic))); + + /* modulo by 1: no remainder */ + if (litVal == 1) + { + ic->op = '='; + IC_RIGHT (ic) = operandFromLit(0); + IC_LEFT (ic) = NULL; + continue; + } + // See if literal value is a power of 2. + while (litVal && !(litVal & 1)) + { + litVal >>= 1; + } + if (litVal) + { + // discard lowest set bit. + litVal >>= 1; + } + + if (!litVal) + { + ic->op = BITWISEAND; + IC_RIGHT(ic) = operandFromLit(operandLitValue(IC_RIGHT(ic)) - 1); + continue; + } + } + /* if long / int mult or divide or mod */ if (ic->op == '*' || ic->op == '/' || ic->op == '%') { @@ -645,15 +894,17 @@ isLocalWithoutDef (symbol * sym) /* replaceRegEqv - replace all local variables with their reqv */ /*-----------------------------------------------------------------*/ static void -replaceRegEqv (eBBlock ** ebbs, int count) +replaceRegEqv (ebbIndex * ebbi) { + eBBlock ** ebbs = ebbi->bbOrder; + int count = ebbi->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); + cseAllBlocks (ebbi, TRUE); for (i = 0; i < count; i++) { @@ -828,8 +1079,10 @@ findReqv (symbol * prereqv, eBBlock ** ebbs, int count) /* killDeadCode - eliminates dead assignments */ /*-----------------------------------------------------------------*/ int -killDeadCode (eBBlock ** ebbs, int count) +killDeadCode (ebbIndex * ebbi) { + eBBlock ** ebbs = ebbi->dfOrder; + int count = ebbi->count; int change = 1; int gchange = 0; int i = 0; @@ -883,7 +1136,8 @@ killDeadCode (eBBlock ** ebbs, int count) if (IC_RESULT (ic) && POINTER_SET (ic)) continue; - if (POINTER_GET (ic) && IS_VOLATILE (operandType (IC_LEFT (ic))->next)) + 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 */ @@ -935,7 +1189,7 @@ killDeadCode (eBBlock ** ebbs, int count) /* 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 == '-')) { @@ -947,6 +1201,16 @@ killDeadCode (eBBlock ** ebbs, int count) 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++; @@ -967,7 +1231,7 @@ killDeadCode (eBBlock ** ebbs, int count) symbol * resultsym = OP_SYMBOL (IC_RESULT (ic)); symbol * prereqv = resultsym->prereqv; - if (OP_SYMBOL (prereqv->reqv) == resultsym) + if (prereqv && prereqv->reqv && (OP_SYMBOL (prereqv->reqv) == resultsym)) { operand * newreqv; @@ -1012,7 +1276,7 @@ killDeadCode (eBBlock ** ebbs, int count) } /* end of all instructions */ if (!ebbs[i]->sch && !ebbs[i]->noPath) - disconBBlock (ebbs[i], ebbs, count); + disconBBlock (ebbs[i], ebbi); } /* end of for all blocks */ @@ -1149,9 +1413,7 @@ optimizeCastCast (eBBlock ** ebbs, int count) eBBlock ** eBBlockFromiCode (iCode * ic) { - eBBlock **ebbs = NULL; - int count = 0; - int saveCount = 0; + ebbIndex *ebbi = NULL; int change = 1; int lchange = 0; int kchange = 0; @@ -1161,7 +1423,6 @@ eBBlockFromiCode (iCode * ic) if (!ic) return NULL; - count = 0; eBBNum = 0; /* optimize the chain for labels & gotos @@ -1170,73 +1431,72 @@ eBBlockFromiCode (iCode * ic) ic = iCodeLabelOptimize (ic); /* break it down into basic blocks */ - ebbs = iCodeBreakDown (ic, &count); - saveCount = count; - + ebbi = iCodeBreakDown (ic); + /* 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); + hashiCodeKeys (ebbi->bbOrder, ebbi->count); /* compute the control flow */ - computeControlFlow (ebbs, count, 0); + computeControlFlow (ebbi); /* dumpraw if asked for */ if (options.dump_raw) - dumpEbbsToFileExt (DUMP_RAW0, ebbs, count); + dumpEbbsToFileExt (DUMP_RAW0, ebbi); /* 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); + replaceRegEqv (ebbi); /* create loop regions */ - loops = createLoopRegions (ebbs, count); + loops = createLoopRegions (ebbi); /* dumpraw if asked for */ if (options.dump_raw) - dumpEbbsToFileExt (DUMP_RAW1, ebbs, count); + dumpEbbsToFileExt (DUMP_RAW1, ebbi); - optimizeCastCast (ebbs, saveCount); + optimizeCastCast (ebbi->bbOrder, ebbi->count); /* do common subexpression elimination for each block */ - change = cseAllBlocks (ebbs, saveCount, FALSE); + change = cseAllBlocks (ebbi, FALSE); /* dumpraw if asked for */ if (options.dump_raw) - dumpEbbsToFileExt (DUMP_CSE, ebbs, count); + dumpEbbsToFileExt (DUMP_CSE, ebbi); /* compute the data flow */ - computeDataFlow (ebbs, saveCount); + computeDataFlow (ebbi); /* dumpraw if asked for */ if (options.dump_raw) - dumpEbbsToFileExt (DUMP_DFLOW, ebbs, count); + dumpEbbsToFileExt (DUMP_DFLOW, ebbi); /* global common subexpression elimination */ if (optimize.global_cse) { - change += cseAllBlocks (ebbs, saveCount, FALSE); + change += cseAllBlocks (ebbi, FALSE); if (options.dump_gcse) - dumpEbbsToFileExt (DUMP_GCSE, ebbs, saveCount); + dumpEbbsToFileExt (DUMP_GCSE, ebbi); } else { // compute the dataflow only - assert(cseAllBlocks (ebbs, saveCount, TRUE)==0); + assert(cseAllBlocks (ebbi, TRUE)==0); } /* kill dead code */ - kchange = killDeadCode (ebbs, saveCount); + kchange = killDeadCode (ebbi); if (options.dump_kill) - dumpEbbsToFileExt (DUMP_DEADCODE, ebbs, count); + dumpEbbsToFileExt (DUMP_DEADCODE, ebbi); /* do loop optimizations */ - change += (lchange = loopOptimizations (loops, ebbs, count)); + change += (lchange = loopOptimizations (loops, ebbi)); if (options.dump_loop) - dumpEbbsToFileExt (DUMP_LOOP, ebbs, count); + dumpEbbsToFileExt (DUMP_LOOP, ebbi); /* recompute the data flow and apply global cse again if loops optimizations or dead code caused a change: @@ -1247,24 +1507,24 @@ eBBlockFromiCode (iCode * ic) subexpression once more */ if (lchange || kchange) { - computeDataFlow (ebbs, saveCount); - change += cseAllBlocks (ebbs, saveCount, FALSE); + computeDataFlow (ebbi); + change += cseAllBlocks (ebbi, FALSE); if (options.dump_loop) - dumpEbbsToFileExt (DUMP_LOOPG, ebbs, count); + dumpEbbsToFileExt (DUMP_LOOPG, ebbi); /* 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); + killDeadCode (ebbi); if (options.dump_loop) - dumpEbbsToFileExt (DUMP_LOOPD, ebbs, count); + dumpEbbsToFileExt (DUMP_LOOPD, ebbi); } /* sort it back by block number */ - qsort (ebbs, saveCount, sizeof (eBBlock *), bbNumCompare); + //qsort (ebbs, saveCount, sizeof (eBBlock *), bbNumCompare); if (!options.lessPedantic) { // this is a good place to check missing return values @@ -1274,9 +1534,9 @@ eBBlockFromiCode (iCode * ic) && !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); + for (bp=setFirstItem(ebbi->bbOrder[ebbi->count-1]->predList); bp; - bp=setNextItem(ebbs[saveCount-1]->predList)) { + bp=setNextItem(ebbi->bbOrder[ebbi->count-1]->predList)) { if (bp->ech->op != RETURN) { werrorfl (bp->ech->filename, bp->ech->lineno, W_VOID_FUNC, currFunc->name); @@ -1288,31 +1548,30 @@ eBBlockFromiCode (iCode * ic) /* if cyclomatic info requested then print it */ if (options.cyclomatic) - printCyclomatic (ebbs, saveCount); + printCyclomatic (ebbi->bbOrder, ebbi->count); /* 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); + convertToFcall (ebbi->bbOrder, ebbi->count); /* compute the live ranges */ - computeLiveRanges (ebbs, count); + computeLiveRanges (ebbi->bbOrder, ebbi->count); if (options.dump_range) - dumpEbbsToFileExt (DUMP_RANGE, ebbs, count); + dumpEbbsToFileExt (DUMP_RANGE, ebbi); /* Now that we have the live ranges, discard parameter * receives for unused parameters. */ - discardDeadParamReceives (ebbs, count); + discardDeadParamReceives (ebbi->bbOrder, ebbi->count); /* allocate registers & generate code */ - port->assignRegisters (ebbs, count); + port->assignRegisters (ebbi); /* throw away blocks */ setToNull ((void *) &graphEdges); - ebbs = NULL; return NULL; }