Changeset: 2fe8f7e3631a for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=2fe8f7e3631a
Modified Files:
        monetdb5/optimizer/opt_dataflow.c
Branch: Feb2013
Log Message:

Simplify dataflow garbagecollection
Introduce a simple pass() operation for all variables that
should be garbage collected while used multiple times in
the dataflow block.
In combination with the dataflow scheduler, it is ensured
that this instruction is really scheduler only after all uses
of the variable has been finished.


diffs (truncated from 319 to 300 lines):

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
@@ -40,7 +40,8 @@ simpleFlow(InstrPtr *old, int start, int
        InstrPtr p = NULL, q;
 
        /* skip simple first */
-       for( ; simple && start < last; start++)  {
+       for( ; simple && start < last; start++)  
+       if ( old[start] ) {
                p= old[start];
                simple = getModuleId(p) == calcRef || getModuleId(p) == 
mtimeRef || getModuleId(p) == strRef || getModuleId(p)== mmathRef;
        }
@@ -55,8 +56,8 @@ simpleFlow(InstrPtr *old, int start, int
                                        simple= TRUE;
                        if( !simple)
                                return 0;
-                       p = q;
                }
+               p = q;
        }
        return 1;
 }
@@ -96,27 +97,12 @@ dflowAssignTest(Lifespan span, InstrPtr 
        return 0;
 }
 
-static int
-dflowUpdateTest(Lifespan span, InstrPtr p, int i)
-{
-       /* Updates are permitted if it is a unique update on 
-        * a BAT created in the context of this block
-        * As far as we know, no SQL nor MAL test re-uses the
-        * target BAT to insert again and subsequently calls dataflow.
-        * In MAL scripts, they still can occur.
-       */
-       (void) span;
-       (void) i;
-       if ( getModuleId(p) == batRef  &&
-          (getFunctionId(p) == insertRef ||
-               getFunctionId(p) == inplaceRef ||
-               getFunctionId(p) == appendRef ||
-               getFunctionId(p) == updateRef ||
-               getFunctionId(p) == replaceRef ||
-               getFunctionId(p) == deleteRef ) )
-                       return FALSE;/* always */
-       return FALSE;
-}
+/* Updates are permitted if it is a unique update on 
+ * a BAT created in the context of this block
+ * As far as we know, no SQL nor MAL test re-uses the
+ * target BAT to insert again and subsequently calls dataflow.
+ * In MAL scripts, they still can occur.
+*/
 
 /* a limited set of MAL instructions may appear in the dataflow block*/
 static int
@@ -134,42 +120,62 @@ dflowInstruction(InstrPtr p) {
 
 static int
 dflowGarbagesink(MalBlkPtr mb, InstrPtr *old, int start, int last, int var, 
InstrPtr *sink, int top){
-       InstrPtr p, q, r;
-       int j,k;
+       InstrPtr r;
        
-       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) {
-                               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;
-               }
-       }
-       assert(top <mb->vsize);
-       sink[top++] = q;
+       (void) start;
+       (void) last;
+       (void) old;
+       r = newInstruction(NULL,ASSIGNsymbol);
+       getModuleId(r) = languageRef;
+       getFunctionId(r) = passRef;
+       getArg(r,0) = newTmpVariable(mb,getVarType(mb,var));
+       r= pushArgument(mb,r, var);
+       sink[top++] = r;
        return top;
 }
 
+static void
+DFLOWinitvars(MalBlkPtr mb, InstrPtr p,int start, int last, Lifespan span, 
char *init)
+{
+       int k;
+       for( k=0; k<p->retc; k++)
+       if( getBeginLifespan(span,getArg(p,k)) >= start && 
getEndLifespan(span,getArg(p,k)) >= last && init[getArg(p,k)]==0){
+               InstrPtr r= newAssignment(mb);
+               getArg(r,0)= getArg(p,k);
+               pushNil(mb,r,getArgType(mb,p,k));
+               init[getArg(p,k)]=1;
+       }
+}
+
+#define copyblock() \
+       for( j=start ; j<i; j++) if (old[j]) pushInstruction(mb,old[j]);\
+       for( j=0; j<top; j++) pushInstruction(mb,sink[j]);
+
+#define exitblock() \
+       if (!sf && entries>1){ \
+               q= newAssignment(mb); \
+               q->barrier= EXITsymbol; \
+               getArg(q,0) = flowblock; \
+       }\
+       memset((char*) usage, 0, vlimit);\
+       entries = flowblock = 0;\
+       actions++;
+
+/* dataflow blocks are transparent, because they are always
+   executed, either sequentially or in parallell */
+#define startblock()\
+       q= newFcnCall(mb,languageRef,dataflowRef);\
+       q->barrier= BARRIERsymbol;\
+       getArg(q,0)= flowblock;\
+       varSetProperty(mb, getArg(q,0), "transparent",0,0);
+
 int
 OPTdataflowImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr 
p)
 {
        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, vlimit, top = 0;
        Lifespan span;
        char *init;
        int *usage;
@@ -191,7 +197,7 @@ OPTdataflowImplementation(Client cntxt, 
                GDKfree(span);
                return 0;
        }
-       usage= (int*) GDKzalloc(mb->vtop * sizeof(int));
+       usage= (int*) GDKzalloc(vlimit = mb->vtop * sizeof(int));
        if ( usage == NULL){
                GDKfree(span);
                GDKfree(init);
@@ -228,7 +234,7 @@ OPTdataflowImplementation(Client cntxt, 
 
                if (p->token == ENDsymbol)
                        break;
-               if (!dflowInstruction(p) || (!dumbcopy && blockExit(p)) || 
dflowAssignTest(span,p,i) || dflowUpdateTest(span,p,i)){
+               if (!dflowInstruction(p) || (!dumbcopy && blockExit(p)) || 
dflowAssignTest(span,p,i) ){
                        /* close old flow block */
                        if (flowblock){
                                int sf = simpleFlow(old,start,i);
@@ -236,43 +242,20 @@ OPTdataflowImplementation(Client cntxt, 
                                if (!sf && entries > 1){
                                        for( j=start ; j<i; 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);
-                                                       getArg(r,0)= 
getArg(old[j],k);
-                                                       
pushNil(mb,r,getArgType(mb,old[j],k));
-                                                       
init[getArg(old[j],k)]=1;
-                                               }
+                                               DFLOWinitvars(mb, old[j], 
start, i, span, init);
                                                /* collect variables garbage 
collected within the block */
                                                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) )
+                                                       if( 
getEndLifespan(span, var = getArg(old[j],k)) == j && usage[var]>=1 && 
isaBatType(getVarType(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) )
+                                                       if( 
getEndLifespan(span,getArg(old[j],k)) < i && isaBatType(getVarType(mb,var)))
                                                                
usage[getArg(old[j],k)]++;
                                                assert(top <mb->vsize);
                                        }
-                                       q= 
newFcnCall(mb,languageRef,dataflowRef);
-                                       q->barrier= BARRIERsymbol;
-                                       getArg(q,0)= flowblock;
-                                       /* dataflow blocks are transparent, 
because they are always
-                                          executed, either sequentially or in 
parallell */
-                                       varSetProperty(mb, getArg(q,0), 
"transparent",0,0);
+                                       startblock();
                                }
-                               for( j=start ; j<i; j++)
-                                       if (old[j])
-                                               pushInstruction(mb,old[j]);
-                               for( j=0; j<top; j++)
-                                               pushInstruction(mb,sink[j]);
-                               if (!sf && entries>1){
-                                       q= newAssignment(mb);
-                                       q->barrier= EXITsymbol;
-                                       getArg(q,0) = flowblock;
-                               }
-                               /* inject the optional garbage sink statement */
-                               entries = 0;
-                               flowblock = 0;
-                               actions++;
+                               copyblock();
+                               exitblock();
                        }
                        pushInstruction(mb,p);
                        continue;
@@ -288,43 +271,20 @@ OPTdataflowImplementation(Client cntxt, 
                                        if (!sf && entries > 1){
                                                for( j=start ; j<i; 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);
-                                                               getArg(r,0)= 
getArg(old[j],k);
-                                                               
pushNil(mb,r,getArgType(mb,old[j],k));
-                                                               
init[getArg(old[j],k)]=1;
-                                                       }
+                                                       DFLOWinitvars(mb, 
old[j], start, i, span, init);
                                                        /* collect variables 
garbagecollected in the block */
                                                        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)]++;
+                                                               if( 
getEndLifespan(span, var = getArg(old[j],k)) == j && usage[var]>=1 && 
isaBatType(getVarType(mb,var)))
+                                                                       top = 
dflowGarbagesink(mb,old, start, i, getArg(old[j],k), sink,top);
+                                                               else
+                                                               if( 
getEndLifespan(span,getArg(old[j],k)) < i && isaBatType(getVarType(mb,var)))
+                                                                       
usage[getArg(old[j],k)]++;
                                                }
-                                               q= 
newFcnCall(mb,languageRef,dataflowRef);
-                                               q->barrier= BARRIERsymbol;
-                                               getArg(q,0)= flowblock;
-                                               /* dataflow blocks are 
transparent, because they are always
-                                                  executed, either 
sequentially or in parallell */
-                                               varSetProperty(mb, getArg(q,0), 
"transparent",0,0);
+                                               startblock();
                                        }
-                                       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;
-                                               getArg(q,0) = flowblock;
-                                       }
-                                       entries = 0;
-                                       flowblock = 0;
-                                       actions++;
+                                       copyblock();
+                                       exitblock();
                                }
                }
                if (blockExit(p)) {
@@ -363,42 +323,18 @@ OPTdataflowImplementation(Client cntxt, 
                if (!sf && entries > 1){
                        for( j=start ; j<i; 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);
-                                       getArg(r,0)= getArg(old[j],k);
-                                       pushNil(mb,r,getArgType(mb,old[j],k));
-                                       init[getArg(old[j],k)]=1;
-                               }
+                               DFLOWinitvars(mb, old[j], start, i, span, init);
                                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)]++;
+                                       if( getEndLifespan(span, var = 
getArg(old[j],k)) == j && usage[var]>=1 && isaBatType(getVarType(mb,var)))
+                                               top = dflowGarbagesink(mb,old, 
start, i, getArg(old[j],k), sink,top);
+                                       else
+                                       if( 
getEndLifespan(span,getArg(old[j],k)) < i && isaBatType(getVarType(mb,var)))
+                                               usage[getArg(old[j],k)]++;
                        }
-                       q= newFcnCall(mb,languageRef,dataflowRef);
-                       q->barrier= BARRIERsymbol;
-                       getArg(q,0)= flowblock;
-                       /* dataflow blocks are transparent, because they are 
always
-                          executed, either sequentially or in parallell */
-                       varSetProperty(mb, getArg(q,0), "transparent",0,0);
+                       startblock();
                }
-               for( j=start ; j<i; j++)
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to