int OPTaccumulatorsImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { int i, limit,slimit; InstrPtr p,q; Module scope = cntxt->nspace; int actions = 0; InstrPtr *old; Lifespan span; (void) pci; (void) stk; /* to fool compilers */ span = setLifespan(mb); if( span == NULL) return 0; old= mb->stmt; limit= mb->stop; slimit= mb->ssize; if ( newMalBlkStmt(mb,mb->stop) < 0){ GDKfree(span); return 0; } for (i = 0; i < limit; i++) { p = old[i]; if( getModuleId(p) != batcalcRef ) { pushInstruction(mb,p); continue; } OPTDEBUGaccumulators printInstruction(cntxt->fdout, mb, 0, p, LIST_MAL_ALL); if (p->retc==1 && p->argc == 2) { /* unary operation, avoid clash with binary */ pushInstruction(mb,p); continue; } if( getLastUpdate(span,getArg(p,0)) != i ) { /* only consider the last update to this variable */ pushInstruction(mb,p); continue; } if (p->retc==1 && p->argc == 3 && isaBatType(getArgType(mb,p,0))) { int b1 =getEndLifespan(span,getArg(p,1))<=i && getArgType(mb,p,1) == getArgType(mb,p,0); int b2 =getEndLifespan(span,getArg(p,2))<=i && getArgType(mb,p,2) == getArgType(mb,p,0) ; if ( b1 == 0 && b2 == 0){ pushInstruction(mb,p); continue; } /* binary/unary operation, check arguments for being candidates */ q= copyInstruction(p); p= pushBit(mb,p, b1); p= pushBit(mb,p, b2); typeChecker(cntxt->fdout, scope, mb, p, TRUE); if (mb->errors || p->typechk == TYPE_UNKNOWN) { OPTDEBUGaccumulators{ mnstr_printf(cntxt->fdout,"# Failed typecheck"); printInstruction(cntxt->fdout, mb, 0, p, LIST_MAL_ALL); } /* reset instruction error buffer */ cntxt->errbuf[0]=0; mb->errors = 0; freeInstruction(p); p=q; /* restore */ } else {
int OPTstrengthReductionImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { int i, j = 0, k, se= FALSE; InstrPtr p; int bk, ik, blk, blkbegin, blkexit, actions = 0; InstrPtr *before, *within, *old = mb->stmt; Lifespan span; (void) cntxt; (void) pci; (void) stk; /* to fool compilers */ before = (InstrPtr *) GDKmalloc((mb->ssize + 1) * sizeof(InstrPtr)); within = (InstrPtr *) GDKmalloc((mb->ssize + 1) * sizeof(InstrPtr)); if (before== NULL || within == NULL){ if(before) GDKfree(before); if(within) GDKfree(within); return 0; } bk = 0; ik = 0; blk = 0; blkexit= blkbegin = 0; for (i = 0; i < mb->stop; i++) before[i] = within[i] = 0; before[bk++] = getInstrPtr(mb, 0); span =setLifespan(mb); if( span == NULL) return 0; for (i = 1; i < mb->stop - 1; i++) { p = getInstrPtr(mb, i); if (blockStart(p)) { if (blkbegin == 0){ if( isLoopBarrier(mb,i) ){ blkbegin = i; blkexit = getBlockExit(mb,i); } OPTDEBUGstrengthReduction mnstr_printf(cntxt->fdout, "#check block %d-%d\n", blkbegin, blkexit); } within[ik++] = p; blk++; continue; } if (blockExit(p)) { blk--; if (blk == 0) blkexit= blkbegin = 0; /* move the saved instruction into place */ OPTDEBUGstrengthReduction mnstr_printf(cntxt->fdout, "#combine both %d %d\n", bk, ik); for (k = 0; k < ik; k++) before[bk++] = within[k]; ik = 0; before[bk++] = p; continue; } /* * @- * Strength reduction is only relevant inside a block; */ if( blkexit == 0) { within[ik++] = p; continue; } /* * @- * Flow control statements may not be moved around */ if ( p->barrier != 0){ within[ik++] = p; continue; } /* * @- * Limit strength reduction to the type modules and the batcalc, batstr, batcolor * and sql.bind. */ if(getModuleId(p) && !isNewSource(p) ) { within[ik++] = p; continue; } /* * @- * Search the prospective new block and make sure that * none of the arguments is assigned a value. */ for (j = ik-1; j > 0; j--) { InstrPtr q = within[j]; for (k = 0; k < q->retc; k++) if (SRoverwritten(p, getArg(q, k))) { se = TRUE; OPTDEBUGstrengthReduction mnstr_printf(cntxt->fdout, "variable is set in loop %d\n", getArg(p, k)); goto noreduction; } } /* * @- * Make sure the variables are not declared before the loop and used * after the loop, because then you may not simple move an expression. */ for (k = 0; k < p->retc; k++) if ( getBeginLifespan(span, getArg(p, k))<= blkbegin || getEndLifespan(span, getArg(p, k))> blkexit) { se = TRUE; OPTDEBUGstrengthReduction mnstr_printf(cntxt->fdout, "variable %d may not be moved %d-%d\n", getArg(p, k),getBeginLifespan(span, getArg(p, k)), getEndLifespan(span, getArg(p, k))); goto noreduction; } noreduction: OPTDEBUGstrengthReduction{ mnstr_printf(cntxt->fdout,"move %d to stack %s\n", i, (se ?"within":"before")); printInstruction(cntxt->fdout, mb, 0, p, LIST_MAL_ALL); } if (blkexit && se == FALSE && !hasSideEffects(p, TRUE) && !isUpdateInstruction(p) ) before[bk++] = p; else within[ik++] = p; } actions += ik; for (k = 0; k < ik; k++) before[bk++] = within[k]; before[bk++] = getInstrPtr(mb, i); GDKfree(mb->stmt); mb->stmt = (InstrPtr *) GDKzalloc((mb->ssize) * sizeof(InstrPtr)); if ( mb->stmt == NULL){ GDKfree(span); GDKfree(before); GDKfree(within); mb->stmt = old; return 0; } mb->stop = 0; OPTDEBUGstrengthReduction mnstr_printf(cntxt->fdout,"stop= %d bk=%d\n",mb->stop,bk); for (i = 0; i < bk; i++) if( before[i]) pushInstruction(mb, before[i]); GDKfree(span); GDKfree(before); GDKfree(within); return actions; }
/* * Keeping variables around beyond their end-of-life-span * can be marked with the proper 'keep'. */ int OPTgarbageCollectorImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { int i, j, k, n = 0, limit, vlimit, depth=0, slimit; InstrPtr p, q, *old; int actions = 0; Lifespan span; (void) pci; (void) cntxt; (void) stk; if (varGetProp(mb, getArg(mb->stmt[0], 0), inlineProp) != NULL) return 0; span = setLifespan(mb); if ( span == NULL) return 0; old= mb->stmt; limit = mb->stop; slimit = mb->ssize; vlimit = mb->vtop; if ( newMalBlkStmt(mb,mb->ssize) < 0) { GDKfree(span); return 0; } p = NULL; for (i = 0; i < limit; i++) { p = old[i]; p->gc &= ~GARBAGECONTROL; if ( p->barrier == RETURNsymbol){ pushInstruction(mb, p); continue; } if (blockStart(p) ) depth++; if ( p->token == ENDsymbol) break; pushInstruction(mb, p); n = mb->stop-1; for (j = 0; j < p->argc; j++) { if (getEndLifespan(span,getArg(p,j)) == i && isaBatType(getArgType(mb, p, j)) ){ mb->var[getArg(p,j)]->eolife = n; p->gc |= GARBAGECONTROL; } } if (blockExit(p) ){ /* force garbage collection of all within upper block */ depth--; for (k = 0; k < vlimit; k++) { if (getBeginLifespan(span,k) > 0 && getEndLifespan(span,k) == i && isaBatType(getVarType(mb,k)) && varGetProp(mb, k, keepProp) == NULL){ q= newAssignment(mb); getArg(q,0) = k; setVarUDFtype(mb,k); setVarFixed(mb,k); q= pushNil(mb,q, getVarType(mb,k)); q->gc |= GARBAGECONTROL; mb->var[k]->eolife = mb->stop-1; actions++; } } } } assert(p); assert( p->token == ENDsymbol); pushInstruction(mb, p); for (i++; i < limit; i++) pushInstruction(mb, old[i]); for (; i < slimit; i++) if (old[i]) freeInstruction(old[i]); getInstrPtr(mb,0)->gc |= GARBAGECONTROL; GDKfree(old); OPTDEBUGgarbageCollector{ int k; mnstr_printf(cntxt->fdout, "#Garbage collected BAT variables \n"); for ( k =0; k < vlimit; k++) mnstr_printf(cntxt->fdout,"%10s eolife %3d begin %3d lastupd %3d end %3d\n", getVarName(mb,k), mb->var[k]->eolife, getBeginLifespan(span,k), getLastUpdate(span,k), getEndLifespan(span,k)); mnstr_printf(cntxt->fdout, "End of GCoptimizer\n"); } GDKfree(span); return actions+1; }