Changeset: bbab2d7ad02d for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=bbab2d7ad02d Modified Files: monetdb5/modules/mal/language.c monetdb5/modules/mal/language.h monetdb5/modules/mal/language.mal monetdb5/optimizer/opt_dataflow.c monetdb5/optimizer/opt_prelude.c monetdb5/optimizer/opt_prelude.h Branch: Feb2013 Log Message:
Improve release of temporaries The sink() operation ensures we handle proper execution of variables used repeatedly at the cost of retaining the temporaries too long. Using the pass() operation turns it into a cheap dataflow dependency. Cheap instruction to disgard storage while retaining the dataflow dependency. diffs (282 lines): diff --git a/monetdb5/modules/mal/language.c b/monetdb5/modules/mal/language.c --- a/monetdb5/modules/mal/language.c +++ b/monetdb5/modules/mal/language.c @@ -152,6 +152,16 @@ MALgarbagesink( Client cntxt, MalBlkPtr return MAL_SUCCEED; } +str +MALpass( Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) +{ + (void) cntxt; + (void) mb; + (void) stk; + (void) pci; + return MAL_SUCCEED; +} + str CMDregisterFunction(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { diff --git a/monetdb5/modules/mal/language.h b/monetdb5/modules/mal/language.h --- a/monetdb5/modules/mal/language.h +++ b/monetdb5/modules/mal/language.h @@ -47,6 +47,7 @@ language_export str MALassertSht(int *re language_export str MALassertInt(int *ret, int *val, str *msg); language_export str MALassertLng(int *ret, lng *val, str *msg); language_export str MALstartDataflow( Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +language_export str MALpass( Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); language_export str MALgarbagesink( Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); language_export str CMDregisterFunction(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); language_export str CMDsetMemoryTrace(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); diff --git a/monetdb5/modules/mal/language.mal b/monetdb5/modules/mal/language.mal --- a/monetdb5/modules/mal/language.mal +++ b/monetdb5/modules/mal/language.mal @@ -39,6 +39,10 @@ address MALgarbagesink comment "Variables to be considered together when triggering garbage collection. Used in the dataflow blocks to avoid early release of values."; +pattern pass(v:any_1):any_1 +address MALpass +comment "Cheap instruction to disgard storage while retaining the dataflow dependency"; + pattern register(m:str,f:str,code:str,help:str):void address CMDregisterFunction comment"Compile the code string to MAL and register it as a function."; diff --git a/monetdb5/optimizer/opt_dataflow.c b/monetdb5/optimizer/opt_dataflow.c --- a/monetdb5/optimizer/opt_dataflow.c +++ b/monetdb5/optimizer/opt_dataflow.c @@ -132,34 +132,44 @@ dflowInstruction(InstrPtr p) { return FALSE; } -static InstrPtr -dflowGarbagesink(MalBlkPtr mb, InstrPtr *old, int start, int last, int var, int *usage){ - InstrPtr p, sink; +static int +dflowGarbagesink(MalBlkPtr mb, InstrPtr *old, int start, int last, int var, InstrPtr *sink, int top){ + InstrPtr p, q, r; int j,k; - if ( usage[var] == 0 || isVarConstant(mb, var) ) - return NULL; - sink= newInstruction(mb,ASSIGNsymbol); - getModuleId(sink) = languageRef; - getFunctionId(sink) = sinkRef; - getArg(sink,0)= newTmpVariable(mb,TYPE_void); - sink= pushArgument(mb, sink, var); + + q= newInstruction(NULL,ASSIGNsymbol); + getModuleId(q) = languageRef; + getFunctionId(q) = sinkRef; + getArg(q,0)= newTmpVariable(mb,TYPE_void); + q= pushArgument(mb, q, var); for ( j= start; j< last; j++){ + assert(top <mb->vsize); p = old[j]; if ( p ) for (k = p->retc; k< p->argc; k++) - if ( getArg(p,k)== var) - sink= pushArgument(mb,sink, getArg(p,0)); + if ( getArg(p,k)== var) { + r = newInstruction(NULL,ASSIGNsymbol); + getModuleId(r) = languageRef; + getFunctionId(r) = passRef; + getArg(r,0) = newTmpVariable(mb,getArgType(mb,p,0)); + r= pushArgument(mb,r, getArg(p,0)); + sink[top++] = r; + q= pushArgument(mb,q, getArg(r,0)); + break; + } } - return sink; + assert(top <mb->vsize); + sink[top++] = q; + return top; } int OPTdataflowImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p) { - int i,j,k, cnt, start=1,entries=0, actions=0; + int i,j,k, var, cnt, start=1,entries=0, actions=0; int flowblock= 0, dumbcopy=0; InstrPtr *sink, *old, q; - int limit, slimit, top = 0; + int limit, slimit, size, top = 0; Lifespan span; char *init; int *usage; @@ -187,18 +197,18 @@ OPTdataflowImplementation(Client cntxt, GDKfree(init); return 0; } - sink= (InstrPtr*) GDKzalloc(mb->stop * sizeof(InstrPtr)); - if ( usage == NULL){ + sink= (InstrPtr*) GDKzalloc(size = mb->vsize * sizeof(InstrPtr)); + if ( sink == NULL){ GDKfree(span); GDKfree(init); - GDKfree(sink); + GDKfree(usage); return 0; } limit= mb->stop; slimit= mb->ssize; old = mb->stmt; - if ( newMalBlkStmt(mb, mb->ssize+20) <0 ){ + if ( newMalBlkStmt(mb, mb->ssize+mb->vtop) <0 ){ GDKfree(span); GDKfree(init); GDKfree(usage); @@ -222,6 +232,7 @@ OPTdataflowImplementation(Client cntxt, /* close old flow block */ if (flowblock){ int sf = simpleFlow(old,start,i); + top = 0; if (!sf && entries > 1){ for( j=start ; j<i; j++) if (old[j]) { @@ -234,13 +245,12 @@ OPTdataflowImplementation(Client cntxt, } /* collect variables garbage collected within the block */ for( k=old[j]->retc; k<old[j]->argc; k++) - if( getEndLifespan(span,getArg(old[j],k)) == j) { - sink[top] = dflowGarbagesink(mb,old, start, i, getArg(old[j],k), usage); - top += sink[top] != NULL; - } - else - if( getEndLifespan(span,getArg(old[j],k)) < i) - usage[getArg(old[j],k)]++; + if( getEndLifespan(span, var = getArg(old[j],k)) == j && usage[var]==1 && !isVarConstant(mb, var) ) + top = dflowGarbagesink(mb,old, start, i, getArg(old[j],k), sink,top); + else + if( getEndLifespan(span,getArg(old[j],k)) < i && !isVarConstant(mb, var) ) + usage[getArg(old[j],k)]++; + assert(top <mb->vsize); } q= newFcnCall(mb,languageRef,dataflowRef); q->barrier= BARRIERsymbol; @@ -254,10 +264,6 @@ OPTdataflowImplementation(Client cntxt, pushInstruction(mb,old[j]); for( j=0; j<top; j++) pushInstruction(mb,sink[j]); - if ( top ) { - top = 0; - memset( (char*) sink, 0, limit * sizeof(InstrPtr)); - } if (!sf && entries>1){ q= newAssignment(mb); q->barrier= EXITsymbol; @@ -278,6 +284,7 @@ OPTdataflowImplementation(Client cntxt, /* close old flow block */ if (flowblock){ int sf = simpleFlow(old,start,i); + top = 0; if (!sf && entries > 1){ for( j=start ; j<i; j++) if (old[j]) { @@ -290,13 +297,11 @@ OPTdataflowImplementation(Client cntxt, } /* collect variables garbagecollected in the block */ for( k=old[j]->retc; k<old[j]->argc; k++) - if( getEndLifespan(span,getArg(old[j],k)) == i) { - sink[top] = dflowGarbagesink(mb, old, start, i, getArg(old[j],k), usage); - top += sink[top] != NULL; - } - else - if( getEndLifespan(span,getArg(old[j],k)) < i) - usage[getArg(old[j],k)]++; + if( getEndLifespan(span, var = getArg(old[j],k)) == j && usage[var]==1 && !isVarConstant(mb, var) ) + top = dflowGarbagesink(mb,old, start, i, getArg(old[j],k), sink,top); + else + if( getEndLifespan(span,getArg(old[j],k)) < i && !isVarConstant(mb, var) ) + usage[getArg(old[j],k)]++; } q= newFcnCall(mb,languageRef,dataflowRef); q->barrier= BARRIERsymbol; @@ -308,13 +313,10 @@ OPTdataflowImplementation(Client cntxt, for( j=start ; j<i; j++) if (old[j]) pushInstruction(mb,old[j]); - /* inject the optional garbage sink statement */ - for( j=0; j<top; j++) - pushInstruction(mb,sink[j]); - if ( top) { - top = 0; - memset( (char*) sink, 0, mb->stop * sizeof(InstrPtr)); - } + assert(top <mb->vsize); + /* inject the optional garbage sink statement */ + for( j=0; j<top; j++) + pushInstruction(mb,sink[j]); if (!sf && entries>1){ q= newAssignment(mb); q->barrier= EXITsymbol; @@ -357,9 +359,10 @@ OPTdataflowImplementation(Client cntxt, /* close old flow block */ if (flowblock){ int sf = simpleFlow(old,start,i); + top = 0; if (!sf && entries > 1){ for( j=start ; j<i; j++) - if (old[j]) + if (old[j]) { for( k=0; k<old[j]->retc; k++) if( getBeginLifespan(span,getArg(old[j],k)) > start && getEndLifespan(span,getArg(old[j],k)) >= i && init[getArg(old[j],k)]==0){ InstrPtr r= newAssignment(mb); @@ -367,6 +370,13 @@ OPTdataflowImplementation(Client cntxt, pushNil(mb,r,getArgType(mb,old[j],k)); init[getArg(old[j],k)]=1; } + for( k=old[j]->retc; k<old[j]->argc; k++) + if( getEndLifespan(span, var = getArg(old[j],k)) == j && usage[var]==1 && !isVarConstant(mb, var) ) + top = dflowGarbagesink(mb,old, start, i, getArg(old[j],k), sink,top); + else + if( getEndLifespan(span,getArg(old[j],k)) < i && !isVarConstant(mb, var) ) + usage[getArg(old[j],k)]++; + } q= newFcnCall(mb,languageRef,dataflowRef); q->barrier= BARRIERsymbol; getArg(q,0)= flowblock; @@ -377,6 +387,10 @@ OPTdataflowImplementation(Client cntxt, for( j=start ; j<i; j++) if (old[j]) pushInstruction(mb,old[j]); + assert(top <mb->vsize); + /* inject the optional garbage sink statement */ + for( j=0; j<top; j++) + pushInstruction(mb,sink[j]); if (!sf && entries>1){ q= newAssignment(mb); q->barrier= EXITsymbol; diff --git a/monetdb5/optimizer/opt_prelude.c b/monetdb5/optimizer/opt_prelude.c --- a/monetdb5/optimizer/opt_prelude.c +++ b/monetdb5/optimizer/opt_prelude.c @@ -167,6 +167,7 @@ str openRef; str optimizerRef; str packRef; str pack2Ref; +str passRef; str partitionRef; str pcreRef; str pinRef; @@ -423,6 +424,7 @@ void optimizerInit(void){ openRef = putName("open",4); packRef = putName("pack",4); pack2Ref = putName("pack2",5); + passRef = putName("pass",4); partitionRef = putName("partition",9); pcreRef = putName("pcre",4); pinRef = putName("pin",3); diff --git a/monetdb5/optimizer/opt_prelude.h b/monetdb5/optimizer/opt_prelude.h --- a/monetdb5/optimizer/opt_prelude.h +++ b/monetdb5/optimizer/opt_prelude.h @@ -166,6 +166,7 @@ opt_export str openRef; opt_export str optimizerRef; opt_export str packRef; opt_export str pack2Ref; +opt_export str passRef; opt_export str partitionRef; opt_export str pcreRef; opt_export str pinRef; _______________________________________________ checkin-list mailing list checkin-list@monetdb.org http://mail.monetdb.org/mailman/listinfo/checkin-list