X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCptropt.c;h=3660bb7f1631b88a4edf09fa6a3a35ee36f0425f;hb=cfe68c56bf38978e8d38fc7356bee7b84ec7b9a6;hp=24e7ccc14c18d9e1303cb546bb56d2bec9a9c1fe;hpb=b09af35f2f1cde7649d3ac4a6f5d2af6d97895a0;p=fw%2Fsdcc diff --git a/src/SDCCptropt.c b/src/SDCCptropt.c index 24e7ccc1..3660bb7f 100644 --- a/src/SDCCptropt.c +++ b/src/SDCCptropt.c @@ -23,167 +23,198 @@ 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 "SDCCcflow.h" -#include "SDCCloop.h" -#include "SDCCcse.h" - - -/*-----------------------------------------------------------------*/ -/* pointerArithOpts - does some pointer arithmetic operations */ -/*-----------------------------------------------------------------*/ - int pointerArithOpts (iCode *ic, hTab *ptrs) +#include "common.h" + +/*-----------------------------------------------------------------------*/ +/* findPointerGetSet - find the pointer get or set for a operand */ +/*-----------------------------------------------------------------------*/ +static iCode * +findPointerGetSet (iCode * sic, operand * op) { - operand *asym ; - long cval; - hashtItem *htip; - induction *ip ; - int lr = 0 ; - - /* the aim here is to reduce the arithmetics performed */ - /* during repeated pointer access . for eg. there are */ - /* lot of places the code generated looks like this */ - /* iTempNN = &[somevar] */ - /* iTempNX = iTempNN + constant-1 */ - /* *(iTempNX) := somevalue */ - /* iTempNY = iTempNN + constant-2 */ - /* *(iTempNY) := somevalue */ - /* we want to change this sequence to */ - /* iTempNN = &[somevar] */ - /* iTempNN = iTempNN + constant-1 */ - /* (*iTempNN) := someValue */ - /* WHY ? this will reduce the number of definitions */ - /* as well as help us in register allocation */ - - /* first check if +/- */ - if (ic->op != '+' && ic->op != '-' ) - return 0; + iCode *ic = sic; - /* if the result is not an iTemp */ - if (!IS_ITEMP(IC_RESULT(ic))) - return 0; + for (; ic; ic = ic->next) + { + if ((POINTER_SET (ic) && isOperandEqual (op, IC_RESULT (ic))) || + (POINTER_GET (ic) && isOperandEqual (op, IC_LEFT (ic)))) + return ic; - /* if +/- then check if one of them is literal */ - if (! IS_OP_LITERAL(IC_LEFT(ic)) && - ! IS_OP_LITERAL(IC_RIGHT(ic)) ) - return 0; + /* if we find any other usage or definition of op null */ + if (IC_RESULT (ic) && isOperandEqual (IC_RESULT (ic), op)) + return NULL; - /* get the operand & literal value */ - if (IS_OP_LITERAL(IC_LEFT(ic))) { - cval = operandLitValue(IC_LEFT(ic)); - asym = IC_RIGHT(ic) ; - } else { - cval = operandLitValue(IC_RIGHT(ic)) ; - lr++ ; - asym = IC_LEFT(ic); - } + if (IC_RIGHT (ic) && isOperandEqual (IC_RIGHT (ic), op)) + return NULL; + + if (IC_LEFT (ic) && isOperandEqual (IC_LEFT (ic), op)) + return NULL; - /* if this symbol does not exist the address of */ - /* or if the symbol is the same as the result */ - if (asym->key == IC_RESULT(ic)->key || - (htip = hTabSearch(ptrs,asym->key)) == NULL ) - return 0; - - ip = htip->item; - - - /* if the constant value in induction is zero */ - /* then we just change the operand */ - if (ip->cval == 0) { - ip->asym = IC_RESULT(ic) ; - ip->cval = cval ; /* update the offset info */ - return 0; - } - /* we can do the substitution */ - replaceAllSymBySym (ic->next, IC_RESULT(ic),ip->asym); - IC_RESULT(ic) = operandFromOperand(ip->asym); - - /* now we know that the constant value is greater than zero */ - /* we have to do some arithmetic here : if the offset is greater */ - /* than what we want then rechange it to subtraction */ - if ( ip->cval > cval) { - ic->op = '-' ; - if (lr) { - IC_LEFT(ic) = operandFromOperand(ip->asym); - IC_RIGHT(ic) = operandFromLit(ip->cval - cval); - } - else { - IC_RIGHT(ic) = operandFromOperand(ip->asym); - IC_LEFT(ic) = operandFromLit(ip->cval - cval); - } - } else { - if (lr) { - IC_LEFT(ic) = operandFromOperand(ip->asym); - IC_RIGHT(ic) = operandFromLit(cval - ip->cval); - } - else { - IC_RIGHT(ic) = operandFromOperand (ip->asym); - IC_LEFT(ic) = operandFromLit(cval - ip->cval); - } } - - ip->cval = cval ; - return 1; + + return NULL; } -/*-----------------------------------------------------------------*/ -/* ptrAopts - pointer arithmetic optimizations for a basic block */ -/*-----------------------------------------------------------------*/ -void ptrAopts (eBBlock **ebbs, int count) +static int pattern1 (iCode *sic) { - int i; - - hTab *pointers ; - - /* for each basic block do */ - for (i = 0 ; i < count ; i++ ) { - iCode *ic; - - setToNull((void **) &pointers); - /* iterate thru intructions in the basic block */ - for (ic = ebbs[i]->sch ; ic ; ic = ic->next ) { - - if (SKIP_IC(ic) ||ic->op == IFX) - continue ; - - if (pointers) - pointerArithOpts(ic,pointers); - - if (!POINTER_SET(ic) && IC_RESULT(ic)) - /* delete from pointer access */ - hTabDeleteItem (&pointers, IC_RESULT(ic)->key,NULL,DELETE_CHAIN,NULL); - - /* set up for pointers */ - if ((ic->op == ADDRESS_OF || ADD_SUBTRACT_ITEMP(ic)) && - IS_ITEMP(IC_RESULT(ic)) ) { - operand *sym ; - operand *asym ; - long cval ; - - if ( ic->op == ADDRESS_OF){ - sym = IC_RESULT(ic); - asym = NULL ; - cval = 0; - } else { - sym = IC_LEFT(ic); - asym = IC_RESULT(ic); - cval = operandLitValue(IC_RIGHT(ic)); - } - - /* put it in the pointer set */ - } - } + /* this is what we do. look for sequences like + + iTempX := _SOME_POINTER_; + iTempY := _SOME_POINTER_ + nn ; nn = sizeof (pointed to object) sic->next + _SOME_POINTER_ := iTempY; sic->next->next + either + iTempZ := @[iTempX]; sic->next->next->next + or + *(iTempX) := ..something.. sic->next->next->next + if we find this then transform this to + iTempX := _SOME_POINTER_; + either + iTempZ := @[iTempX]; + or + *(iTempX) := ..something.. + iTempY := _SOME_POINTER_ + nn ; nn = sizeof (pointed to object) + _SOME_POINTER_ := iTempY; */ + + /* sounds simple enough so lets start , here I use -ve + tests all the way to return if any test fails */ + iCode *pgs, *sh, *st; + + if (!(sic->next && sic->next->next && sic->next->next->next)) + return 0; + if (sic->next->op != '+' && sic->next->op != '-') + return 0; + if (!(sic->next->next->op == '=' && + !POINTER_SET (sic->next->next))) + return 0; + if (!isOperandEqual (IC_LEFT (sic->next), IC_RIGHT (sic)) || + !IS_OP_LITERAL (IC_RIGHT (sic->next))) + return 0; + if (operandLitValue (IC_RIGHT (sic->next)) != + getSize (operandType (IC_RIGHT (sic))->next)) + return 0; + if (!isOperandEqual (IC_RESULT (sic->next->next), + IC_RIGHT (sic))) + return 0; + if (!isOperandEqual (IC_RESULT (sic->next), IC_RIGHT (sic->next->next))) + return 0; + if (!(pgs = findPointerGetSet (sic->next->next, IC_RESULT (sic)))) + return 0; + + /* found the patter .. now do the transformation */ + sh = sic->next; + st = sic->next->next; + + /* take the two out of the chain */ + sic->next = st->next; + st->next->prev = sic; + + /* and put them after the pointer get/set icode */ + if ((st->next = pgs->next)) + st->next->prev = st; + pgs->next = sh; + sh->prev = pgs; + return 1; +} - } +static int pattern2 (iCode *sic) +{ + /* this is what we do. look for sequences like + + iTempX := _SOME_POINTER_; + iTempY := _SOME_POINTER_ + nn ; nn = sizeof (pointed to object) sic->next + iTempK := iTempY; sic->next->next + _SOME_POINTER_ := iTempK; sic->next->next->next + either + iTempZ := @[iTempX]; sic->next->next->next->next + or + *(iTempX) := ..something.. sic->next->next->next->next + if we find this then transform this to + iTempX := _SOME_POINTER_; + either + iTempZ := @[iTempX]; + or + *(iTempX) := ..something.. + iTempY := _SOME_POINTER_ + nn ; nn = sizeof (pointed to object) + iTempK := iTempY; + _SOME_POINTER_ := iTempK; */ + + /* sounds simple enough so lets start , here I use -ve + tests all the way to return if any test fails */ + iCode *pgs, *sh, *st; + + if (!(sic->next && sic->next->next && sic->next->next->next && + sic->next->next->next->next)) + return 0; + + /* yes I can OR them together and make one large if... but I have + simple mind and like to keep things simple & readable */ + if (!(sic->next->op == '+' || sic->next->op == '-')) return 0; + if (!isOperandEqual(IC_RIGHT(sic),IC_LEFT(sic->next))) return 0; + if (!IS_OP_LITERAL (IC_RIGHT (sic->next))) return 0; + if (operandLitValue (IC_RIGHT (sic->next)) != + getSize (operandType (IC_RIGHT (sic))->next)) return 0; + if (!IS_ASSIGN_ICODE(sic->next->next)) return 0; + if (!isOperandEqual(IC_RIGHT(sic->next->next),IC_RESULT(sic->next))) return 0; + if (!IS_ASSIGN_ICODE(sic->next->next->next)) return 0; + if (!isOperandEqual(IC_RIGHT(sic->next->next->next),IC_RESULT(sic->next->next))) return 0; + if (!isOperandEqual(IC_RESULT(sic->next->next->next),IC_LEFT(sic->next))) return 0; + if (!(pgs = findPointerGetSet (sic->next->next->next, IC_RESULT (sic)))) return 0; + + /* found the patter .. now do the transformation */ + sh = sic->next; + st = sic->next->next->next; + + /* take the three out of the chain */ + sic->next = st->next; + st->next->prev = sic; + + /* and put them after the pointer get/set icode */ + if ((st->next = pgs->next)) + st->next->prev = st; + pgs->next = sh; + sh->prev = pgs; + return 1; +} + +/*-----------------------------------------------------------------------*/ +/* ptrPostIncDecOpts - will do some pointer post increment optimizations */ +/* this will help register allocation amongst others */ +/*-----------------------------------------------------------------------*/ +void +ptrPostIncDecOpt (iCode * sic) +{ + if (pattern1(sic)) return ; + pattern2(sic); +} + +/*-----------------------------------------------------------------------*/ +/* addPattern1 - transform addition to pointer of variables */ +/*-----------------------------------------------------------------------*/ +static int addPattern1(iCode *ic) +{ + iCode *dic; + operand *tmp; + /* transform : + iTempAA = iTempBB + iTempCC + iTempDD = iTempAA + CONST + to + iTempAA = iTempBB + CONST + iTempDD = iTempAA + iTempCC + */ + if (!isOperandLiteral(IC_RIGHT(ic))) return 0; + if ((dic=findBackwardDef(IC_LEFT(ic),ic->prev)) == NULL) return 0; + if (bitVectnBitsOn(OP_SYMBOL(IC_RESULT(dic))->uses) > 1) return 0; + if (dic->op != '+') return 0; + tmp = IC_RIGHT(ic); + IC_RIGHT(ic) = IC_RIGHT(dic); + IC_RIGHT(dic) = tmp; + return 1; +} + +/*-----------------------------------------------------------------------*/ +/* ptrAddition - optimize pointer additions */ +/*-----------------------------------------------------------------------*/ +int ptrAddition (iCode *sic) +{ + if (addPattern1(sic)) return 1; + return 0; }