|
@@ -6,20 +6,56 @@ private class Exit {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+private class VarRel {
|
|
|
|
+ public var v : VarDeps;
|
|
|
|
+ public var fields : Int = 0;
|
|
|
|
+ public function new(v) {
|
|
|
|
+ this.v = v;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
private class VarDeps {
|
|
private class VarDeps {
|
|
public var v : TVar;
|
|
public var v : TVar;
|
|
- public var keep : Bool;
|
|
|
|
- public var used : Bool;
|
|
|
|
- public var deps : Map<Int,VarDeps>;
|
|
|
|
- public var adeps : Array<VarDeps>;
|
|
|
|
|
|
+ public var keep : Int = 0;
|
|
|
|
+ public var used : Int = 0;
|
|
|
|
+ public var deps : Map<Int,VarRel>;
|
|
|
|
+ public var adeps : Array<VarRel>;
|
|
public function new(v) {
|
|
public function new(v) {
|
|
this.v = v;
|
|
this.v = v;
|
|
- used = false;
|
|
|
|
deps = new Map();
|
|
deps = new Map();
|
|
adeps = [];
|
|
adeps = [];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+private class WriteTo {
|
|
|
|
+ public var vars : Array<VarDeps>;
|
|
|
|
+ public var bits : Array<Int>;
|
|
|
|
+ public function new() {
|
|
|
|
+ vars = [];
|
|
|
|
+ bits = [];
|
|
|
|
+ }
|
|
|
|
+ public function push(v,b) {
|
|
|
|
+ vars.push(v);
|
|
|
|
+ bits.push(b);
|
|
|
|
+ }
|
|
|
|
+ public function pop() {
|
|
|
|
+ vars.pop();
|
|
|
|
+ bits.pop();
|
|
|
|
+ }
|
|
|
|
+ public function append( v: VarDeps, b : Int ) {
|
|
|
|
+ for( i => v2 in vars )
|
|
|
|
+ if( v2 == v ) {
|
|
|
|
+ bits[i] |= b;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ push(v,b);
|
|
|
|
+ }
|
|
|
|
+ public function appendTo( w : WriteTo ) {
|
|
|
|
+ for( i => v in vars )
|
|
|
|
+ w.append(v, bits[i]);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
class Dce {
|
|
class Dce {
|
|
|
|
|
|
var used : Map<Int,VarDeps>;
|
|
var used : Map<Int,VarDeps>;
|
|
@@ -48,14 +84,14 @@ class Dce {
|
|
if( v.kind == Input )
|
|
if( v.kind == Input )
|
|
inputs.push(i);
|
|
inputs.push(i);
|
|
if( v.kind == Output || v.type.match(TBuffer(_,_,RW) | TRWTexture(_)) )
|
|
if( v.kind == Output || v.type.match(TBuffer(_,_,RW) | TRWTexture(_)) )
|
|
- i.keep = true;
|
|
|
|
|
|
+ i.keep = 15;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// collect dependencies
|
|
// collect dependencies
|
|
for( s in shaders ) {
|
|
for( s in shaders ) {
|
|
for( f in s.funs )
|
|
for( f in s.funs )
|
|
- check(f.expr, [], []);
|
|
|
|
|
|
+ check(f.expr, new WriteTo(), new WriteTo());
|
|
}
|
|
}
|
|
|
|
|
|
var outExprs = [];
|
|
var outExprs = [];
|
|
@@ -64,13 +100,13 @@ class Dce {
|
|
debug("DCE LOOP");
|
|
debug("DCE LOOP");
|
|
|
|
|
|
for( v in used )
|
|
for( v in used )
|
|
- if( v.keep )
|
|
|
|
- markRec(v);
|
|
|
|
|
|
+ if( v.keep != 0 )
|
|
|
|
+ markRec(v, v.keep);
|
|
|
|
|
|
- while( inputs.length > 1 && !inputs[inputs.length - 1].used )
|
|
|
|
|
|
+ while( inputs.length > 1 && inputs[inputs.length - 1].used == 0 )
|
|
inputs.pop();
|
|
inputs.pop();
|
|
for( v in inputs )
|
|
for( v in inputs )
|
|
- markRec(v);
|
|
|
|
|
|
+ markRec(v, 15);
|
|
|
|
|
|
outExprs = [];
|
|
outExprs = [];
|
|
for( s in shaders ) {
|
|
for( s in shaders ) {
|
|
@@ -91,7 +127,7 @@ class Dce {
|
|
}
|
|
}
|
|
|
|
|
|
for( v in used ) {
|
|
for( v in used ) {
|
|
- if( v.used ) continue;
|
|
|
|
|
|
+ if( v.used != 0 ) continue;
|
|
if( v.v.kind == VarKind.Input) continue;
|
|
if( v.v.kind == VarKind.Input) continue;
|
|
for( s in shaders )
|
|
for( s in shaders )
|
|
s.vars.remove(v.v);
|
|
s.vars.remove(v.v);
|
|
@@ -109,82 +145,116 @@ class Dce {
|
|
return vd;
|
|
return vd;
|
|
}
|
|
}
|
|
|
|
|
|
- function markRec( v : VarDeps ) {
|
|
|
|
- if( v.used ) return;
|
|
|
|
- debug(v.v.name+" is used");
|
|
|
|
- v.used = true;
|
|
|
|
- for( d in v.adeps )
|
|
|
|
- markRec(d);
|
|
|
|
|
|
+ function swizStr( bits : Int ) {
|
|
|
|
+ if( bits == 15 )
|
|
|
|
+ return "";
|
|
|
|
+ var str = ".";
|
|
|
|
+ if( bits & 1 != 0 ) str += "x";
|
|
|
|
+ if( bits & 2 != 0 ) str += "y";
|
|
|
|
+ if( bits & 4 != 0 ) str += "z";
|
|
|
|
+ if( bits & 8 != 0 ) str += "w";
|
|
|
|
+ return str;
|
|
}
|
|
}
|
|
|
|
|
|
- function link( v : TVar, writeTo : Array<VarDeps> ) {
|
|
|
|
|
|
+ function markRec( v : VarDeps, bits : Int ) {
|
|
|
|
+ if( v.used & bits == bits ) return;
|
|
|
|
+ bits &= ~v.used;
|
|
|
|
+ debug(v.v.name+swizStr(bits)+" is used");
|
|
|
|
+ v.used |= bits;
|
|
|
|
+ for( d in v.adeps ) {
|
|
|
|
+ var mask = makeFieldsBits(15, bits);
|
|
|
|
+ if( d.fields & mask != 0 )
|
|
|
|
+ markRec(d.v, extractFieldsBits(d.fields,bits));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ function extractFieldsBits( fields : Int, write : Int ) {
|
|
|
|
+ return ((write & 1 == 0 ? 0 : fields) | (write & 2 == 0 ? 0 : fields>>4) | (write & 4 == 0 ? 0 : fields>>8) | (write & 8 == 0 ? 0 : fields>>12)) & 15;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ function makeFieldsBits( read : Int, write : Int ) {
|
|
|
|
+ return write * ((read & 1) + ((read & 2) << 3) + ((read & 4) << 6) + ((read & 8) << 9));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ function link( v : TVar, writeTo : WriteTo, bits = 15 ) {
|
|
var vd = get(v);
|
|
var vd = get(v);
|
|
- for( w in writeTo ) {
|
|
|
|
|
|
+ for( i => w in writeTo.vars ) {
|
|
if( w == null ) {
|
|
if( w == null ) {
|
|
// mark for conditional
|
|
// mark for conditional
|
|
- if( !vd.keep ) {
|
|
|
|
|
|
+ if( vd.keep == 0 ) {
|
|
debug("Force keep "+vd.v.name);
|
|
debug("Force keep "+vd.v.name);
|
|
- vd.keep = true;
|
|
|
|
|
|
+ vd.keep = 15;
|
|
markAsKeep = true;
|
|
markAsKeep = true;
|
|
}
|
|
}
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
- if( !w.deps.exists(v.id) ) {
|
|
|
|
- debug(w.v.name+" depends on "+vd.v.name);
|
|
|
|
- w.deps.set(v.id, vd);
|
|
|
|
- w.adeps.push(vd);
|
|
|
|
|
|
+ var d = w.deps.get(v.id);
|
|
|
|
+ if( d == null ) {
|
|
|
|
+ d = new VarRel(vd);
|
|
|
|
+ w.deps.set(v.id, d);
|
|
|
|
+ w.adeps.push(d);
|
|
|
|
+ }
|
|
|
|
+ var fields = makeFieldsBits(bits, writeTo.bits[i]);
|
|
|
|
+ if( d.fields & fields != fields ) {
|
|
|
|
+ d.fields |= fields;
|
|
|
|
+ debug(w.v.name+swizStr(writeTo.bits[i])+" depends on "+vd.v.name+swizStr(bits));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- function check( e : TExpr, writeTo : Array<VarDeps>, isAffected : Array<VarDeps> ) : Void {
|
|
|
|
|
|
+ function swizBits( sw : Array<Component> ) {
|
|
|
|
+ var b = 0;
|
|
|
|
+ for( c in sw )
|
|
|
|
+ b |= 1 << c.getIndex();
|
|
|
|
+ return b;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ function check( e : TExpr, writeTo : WriteTo, isAffected : WriteTo ) : Void {
|
|
switch( e.e ) {
|
|
switch( e.e ) {
|
|
case TVar(v):
|
|
case TVar(v):
|
|
link(v, writeTo);
|
|
link(v, writeTo);
|
|
- case TBinop(OpAssign | OpAssignOp(_), { e : (TVar(v) | TSwiz( { e : TVar(v) }, _)) }, e):
|
|
|
|
|
|
+ case TSwiz({ e : TVar(v) }, swiz):
|
|
|
|
+ link(v, writeTo, swizBits(swiz));
|
|
|
|
+ case TBinop(OpAssign | OpAssignOp(_), { e : TVar(v) }, e):
|
|
var v = get(v);
|
|
var v = get(v);
|
|
- writeTo.push(v);
|
|
|
|
|
|
+ writeTo.push(v,15);
|
|
check(e, writeTo, isAffected);
|
|
check(e, writeTo, isAffected);
|
|
writeTo.pop();
|
|
writeTo.pop();
|
|
- if( isAffected.indexOf(v) < 0 )
|
|
|
|
- isAffected.push(v);
|
|
|
|
|
|
+ isAffected.append(v,15);
|
|
|
|
+ case TBinop(OpAssign | OpAssignOp(_), { e : TSwiz({ e : TVar(v) },swiz) }, e):
|
|
|
|
+ var v = get(v);
|
|
|
|
+ var bits = swizBits(swiz);
|
|
|
|
+ writeTo.push(v,bits);
|
|
|
|
+ check(e, writeTo, isAffected);
|
|
|
|
+ writeTo.pop();
|
|
|
|
+ isAffected.append(v,bits);
|
|
case TBinop(OpAssign | OpAssignOp(_), { e : (TArray({ e: TVar(v) }, i) | TSwiz({ e : TArray({ e : TVar(v) }, i) },_) | TField({e : TArray({ e : TVar(v) }, i) }, _)) }, e):
|
|
case TBinop(OpAssign | OpAssignOp(_), { e : (TArray({ e: TVar(v) }, i) | TSwiz({ e : TArray({ e : TVar(v) }, i) },_) | TField({e : TArray({ e : TVar(v) }, i) }, _)) }, e):
|
|
var v = get(v);
|
|
var v = get(v);
|
|
- writeTo.push(v);
|
|
|
|
|
|
+ writeTo.push(v,15);
|
|
check(i, writeTo, isAffected);
|
|
check(i, writeTo, isAffected);
|
|
check(e, writeTo, isAffected);
|
|
check(e, writeTo, isAffected);
|
|
writeTo.pop();
|
|
writeTo.pop();
|
|
- if( isAffected.indexOf(v) < 0 )
|
|
|
|
- isAffected.push(v);
|
|
|
|
|
|
+ isAffected.append(v,15);
|
|
case TBlock(el):
|
|
case TBlock(el):
|
|
- var noWrite = [];
|
|
|
|
|
|
+ var noWrite = new WriteTo();
|
|
for( i in 0...el.length )
|
|
for( i in 0...el.length )
|
|
check(el[i],i < el.length - 1 ? noWrite : writeTo, isAffected);
|
|
check(el[i],i < el.length - 1 ? noWrite : writeTo, isAffected);
|
|
case TVarDecl(v, init) if( init != null ):
|
|
case TVarDecl(v, init) if( init != null ):
|
|
- writeTo.push(get(v));
|
|
|
|
|
|
+ writeTo.push(get(v),15);
|
|
check(init, writeTo, isAffected);
|
|
check(init, writeTo, isAffected);
|
|
writeTo.pop();
|
|
writeTo.pop();
|
|
case TIf(e, eif, eelse):
|
|
case TIf(e, eif, eelse):
|
|
- var affect = [];
|
|
|
|
|
|
+ var affect = new WriteTo();
|
|
check(eif, writeTo, affect);
|
|
check(eif, writeTo, affect);
|
|
if( eelse != null ) check(eelse, writeTo, affect);
|
|
if( eelse != null ) check(eelse, writeTo, affect);
|
|
- var len = affect.length;
|
|
|
|
- for( v in writeTo )
|
|
|
|
- if( affect.indexOf(v) < 0 )
|
|
|
|
- affect.push(v);
|
|
|
|
|
|
+ affect.appendTo(isAffected);
|
|
|
|
+ writeTo.appendTo(affect);
|
|
check(e, affect, isAffected);
|
|
check(e, affect, isAffected);
|
|
- for( i in 0...len ) {
|
|
|
|
- var v = affect[i];
|
|
|
|
- if( isAffected.indexOf(v) < 0 )
|
|
|
|
- isAffected.push(v);
|
|
|
|
- }
|
|
|
|
case TFor(v, it, loop):
|
|
case TFor(v, it, loop):
|
|
- var affect = [];
|
|
|
|
|
|
+ var affect = new WriteTo();
|
|
check(loop, writeTo, affect);
|
|
check(loop, writeTo, affect);
|
|
|
|
+ affect.appendTo(isAffected);
|
|
check(it, affect, isAffected);
|
|
check(it, affect, isAffected);
|
|
- for( v in affect )
|
|
|
|
- if( isAffected.indexOf(v) < 0 )
|
|
|
|
- isAffected.push(v);
|
|
|
|
case TCall({ e : TGlobal(ChannelRead) }, [{ e : TVar(c) }, uv, { e : TConst(CInt(cid)) }]):
|
|
case TCall({ e : TGlobal(ChannelRead) }, [{ e : TVar(c) }, uv, { e : TConst(CInt(cid)) }]):
|
|
check(uv, writeTo, isAffected);
|
|
check(uv, writeTo, isAffected);
|
|
if( channelVars[cid] == null ) {
|
|
if( channelVars[cid] == null ) {
|
|
@@ -204,12 +274,11 @@ class Dce {
|
|
}
|
|
}
|
|
case TCall({ e : TGlobal(ImageStore)}, [{ e : TVar(v) }, uv, val]):
|
|
case TCall({ e : TGlobal(ImageStore)}, [{ e : TVar(v) }, uv, val]):
|
|
var v = get(v);
|
|
var v = get(v);
|
|
- writeTo.push(v);
|
|
|
|
|
|
+ writeTo.push(v,15);
|
|
check(uv, writeTo, isAffected);
|
|
check(uv, writeTo, isAffected);
|
|
check(val, writeTo, isAffected);
|
|
check(val, writeTo, isAffected);
|
|
writeTo.pop();
|
|
writeTo.pop();
|
|
- if( isAffected.indexOf(v) < 0 )
|
|
|
|
- isAffected.push(v);
|
|
|
|
|
|
+ isAffected.append(v,15);
|
|
default:
|
|
default:
|
|
e.iter(check.bind(_, writeTo, isAffected));
|
|
e.iter(check.bind(_, writeTo, isAffected));
|
|
}
|
|
}
|
|
@@ -219,8 +288,9 @@ class Dce {
|
|
// found a branch with side effect left, this condition vars needs to be kept
|
|
// found a branch with side effect left, this condition vars needs to be kept
|
|
switch( e.e ) {
|
|
switch( e.e ) {
|
|
case TIf(cond, _, _):
|
|
case TIf(cond, _, _):
|
|
- var writeTo = [null];
|
|
|
|
- check(cond, writeTo, []);
|
|
|
|
|
|
+ var writeTo = new WriteTo();
|
|
|
|
+ writeTo.append(null,0);
|
|
|
|
+ check(cond, writeTo, new WriteTo());
|
|
default:
|
|
default:
|
|
}
|
|
}
|
|
e.iter(checkBranches);
|
|
e.iter(checkBranches);
|
|
@@ -239,7 +309,7 @@ class Dce {
|
|
count++;
|
|
count++;
|
|
}
|
|
}
|
|
return { e : TBlock(out), p : e.p, t : e.t };
|
|
return { e : TBlock(out), p : e.p, t : e.t };
|
|
- case TVarDecl(v,_) | TBinop(OpAssign | OpAssignOp(_), { e : (TVar(v) | TSwiz( { e : TVar(v) }, _) | TArray( { e : TVar(v) }, _)) }, _) if( !get(v).used ):
|
|
|
|
|
|
+ case TVarDecl(v,_) | TBinop(OpAssign | OpAssignOp(_), { e : (TVar(v) | TSwiz( { e : TVar(v) }, _) | TArray( { e : TVar(v) }, _)) }, _) if( get(v).used == 0 ):
|
|
return { e : TConst(CNull), t : e.t, p : e.p };
|
|
return { e : TConst(CNull), t : e.t, p : e.p };
|
|
case TCall({ e : TGlobal(ChannelRead) }, [_, uv, { e : TConst(CInt(cid)) }]):
|
|
case TCall({ e : TGlobal(ChannelRead) }, [_, uv, { e : TConst(CInt(cid)) }]):
|
|
var c = channelVars[cid];
|
|
var c = channelVars[cid];
|