From 662cb28e6a7cdf4561dffb0f3e62ff5350d66a1b Mon Sep 17 00:00:00 2001 From: Laurent Le Brun Date: Wed, 4 Jan 2023 00:58:24 +0100 Subject: [PATCH] Augmented operators: x=x+... becomes x+= Data point: this saves 28 bytes before compression, but not even a byte after compression --- README.md | 23 +++++++++++++++++++ src/rewriter.fs | 8 +++++++ tests/commands.txt | 1 + tests/compression_results.log | 12 +++++----- tests/real/kinder_painter.expected | 14 +++++------ tests/real/mandelbulb.expected | 10 ++++---- tests/real/slisesix.frag.expected | 6 ++--- tests/real/terrarium.frag.expected | 18 +++++++-------- ...real_party_is_in_your_pocket.frag.expected | 2 +- tests/unit/augmented.frag | 13 +++++++++++ tests/unit/augmented.frag.expected | 14 +++++++++++ 11 files changed, 90 insertions(+), 31 deletions(-) create mode 100644 tests/unit/augmented.frag create mode 100644 tests/unit/augmented.frag.expected diff --git a/README.md b/README.md index f65d435d..0eb4a029 100644 --- a/README.md +++ b/README.md @@ -467,6 +467,29 @@ be an issue. Disable this transformation with the flag `--no-move-declarations`. +### Augmented operators + +We use the augmented operators (e.g. `+=`) where possible. + +Input: +```glsl +spe=spe*spe; +x=x-.5; +a=a+(a<<3); +a=a^a>>15; +``` + +Output: +```glsl +spe*=spe; +x-=.5; +a+=a<<3; +a^=a>>15; +``` + +This transformation always reduces the size of the output. However, this seems +to have negligible impact on the size after compression. + ### Rename vector fields To access fields of a vector, it is possible to use `.rgba` fields, or `.xyzw`, diff --git a/src/rewriter.fs b/src/rewriter.fs index b7c56fca..9a1052f6 100644 --- a/src/rewriter.fs +++ b/src/rewriter.fs @@ -97,6 +97,9 @@ let (|Number|_|) = function | Float (f, _) -> Some f | _ -> None +let augmentableOperators = set ["+"; "-"; "*"; "/"; "%"; "<<"; ">>"; "&"; "^"; "|"] + + let private simplifyOperator env = function | FunCall(Op "-", [Int (i1, su)]) -> Int (-i1, su) | FunCall(Op "-", [FunCall(Op "-", [e])]) -> e @@ -173,6 +176,11 @@ let private simplifyOperator env = function // x-(y-z) -> x-y+z | FunCall(Op "-", [x; FunCall(Op "-", [y; z])]) -> FunCall(Op "+", [FunCall(Op "-", [x; y]); z]) |> env.fExpr env + + // Match: x = x + ... + | FunCall(Op "=", [Var x; FunCall(Op op, [Var y; e])]) + when x.Name = y.Name && augmentableOperators.Contains op -> + FunCall(Op (op + "="), [Var x; e]) | e -> e diff --git a/tests/commands.txt b/tests/commands.txt index db549dc4..9e73185e 100644 --- a/tests/commands.txt +++ b/tests/commands.txt @@ -21,6 +21,7 @@ --no-renaming --no-inlining --format indented -o tests/unit/pi.frag.expected tests/unit/pi.frag --no-renaming --no-inlining --format indented -o tests/unit/vectors.frag.expected tests/unit/vectors.frag --no-renaming --format indented -o tests/unit/deadcode.frag.expected tests/unit/deadcode.frag +--no-renaming --no-inlining --format indented -o tests/unit/augmented.frag.expected tests/unit/augmented.frag # Inlining unit tests diff --git a/tests/compression_results.log b/tests/compression_results.log index 521294cb..f3424abc 100644 --- a/tests/compression_results.log +++ b/tests/compression_results.log @@ -1,17 +1,17 @@ from-the-seas-to-the-stars.frag 14347 => 2353.607 -the_real_party_is_in_your_pocket.frag 12214 => 1829.362 +the_real_party_is_in_your_pocket.frag 12213 => 1829.362 ed-209.frag 7899 => 1359.091 valley_ball.glsl 4419 => 896.357 lunaquatic.frag 5232 => 1056.700 -slisesix.frag 4546 => 957.481 +slisesix.frag 4543 => 958.065 yx_long_way_from_home.frag 2993 => 614.607 oscars_chair.frag 4649 => 982.393 -kinder_painter.frag 2901 => 456.603 +kinder_painter.frag 2894 => 456.030 ohanami.frag 3293 => 746.366 -terrarium.frag 3646 => 748.815 +terrarium.frag 3633 => 749.292 leizex.frag 2308 => 515.785 elevated.hlsl 3406 => 611.302 buoy.frag 4237 => 630.724 orchard.frag 5618 => 1058.054 -robin.frag 6298 => 1067.719 -Total: 88006 => 15884.964 +robin.frag 6294 => 1066.421 +Total: 87978 => 15884.156 diff --git a/tests/real/kinder_painter.expected b/tests/real/kinder_painter.expected index 21ac0d8a..b460a112 100644 --- a/tests/real/kinder_painter.expected +++ b/tests/real/kinder_painter.expected @@ -54,12 +54,12 @@ "{" "vec3 nor;" "if(col.w>2.5)" - "nor.xz=inter.xz-obj.xz,nor.y=0.,nor=nor/obj.w,uv=vec2(nor.x,inter.y);" + "nor.xz=inter.xz-obj.xz,nor.y=0.,nor/=obj.w,uv=vec2(nor.x,inter.y);" "else" " if(col.w>1.5)" "nor=obj.xyz,uv=inter.xz*.2;" "else" - " nor=inter-obj.xyz,nor=nor/obj.w,uv=nor.xy;" + " nor=inter-obj.xyz,nor/=obj.w,uv=nor.xy;" "return nor;" "}" "vec4 cmov(vec4 a,vec4 b,bool cond)" @@ -131,8 +131,8 @@ "ref.xyz=reflect(rd,nor);" "spe=dot(ref.xyz,luz.xyz);" "spe=max(spe,0.);" - "spe=spe*spe;" - "spe=spe*spe;" + "spe*=spe;" + "spe*=spe;" "if(intersectShadow(inter,luz.xyz,luz.w))" "dif=0.;" "col*=texture2D(tex0,uv);" @@ -141,8 +141,8 @@ "dif=dot(nor,-rd);" "ref.w=dif;" "dif=1.-dif*dif;" - "dif=dif*dif;" - "col=col+.35*vec4(dif);" + "dif*=dif;" + "col+=.35*vec4(dif);" "return col;" "}" "void main()" @@ -174,7 +174,7 @@ "luz.xyz=luz.xyz/luz.w;" "col=basicShade(inter,obj,col,rd,luz,ref);" "tmin=intersect(inter,ref.xyz,obj,col2);" - "inter=inter+ref.xyz*tmin;" + "inter+=ref.xyz*tmin;" "luz.xyz=vec3(0,1.5,-1)-inter;" "luz.w=length(luz.xyz);" "luz.xyz=luz.xyz/luz.w;" diff --git a/tests/real/mandelbulb.expected b/tests/real/mandelbulb.expected index e977b683..7b959b31 100644 --- a/tests/real/mandelbulb.expected +++ b/tests/real/mandelbulb.expected @@ -28,11 +28,11 @@ const char *mandelbulb_frag = "for(int t=1;t<7;t++)" "{" "\n#if 0\n" - "float z=sqrt(dot(i,i)),c=acos(i.y/z),o=atan(i.x,i.z);" + "float z=sqrt(dot(i,i)),o=acos(i.y/z),c=atan(i.x,i.z);" "z=pow(z,8.);" - "c=c*8.;" - "o=o*8.;" - "i=v+z*vec3(sin(c)*sin(o),cos(c),sin(c)*cos(o));" + "o*=8.;" + "c*=8.;" + "i=v+z*vec3(sin(o)*sin(c),cos(o),sin(o)*cos(c));" "\n#else\n" "float s=i.x,d=s*s,n=d*d,m=i.y,l=m*m,p=i.z,w=p*p,r=w*w,g=d+w,a=inversesqrt(g*g*g*g*g*g*g),u=n+l*l+r-6.*l*w-6.*d*l+2.*w*d,q=d-l+w;" "i.x=v.x+64.*s*m*p*(d-w)*q*(n-6.*d*w+r)*u*a;" @@ -100,7 +100,7 @@ const char *mandelbulb_frag = "{" "vec3 m=c+u*s,a;" "float q=clamp(.2+.8*dot(f,n),0.,1.),b,F,C;" - "q=q*q;" + "q*=q;" "b=clamp(.3+.7*dot(o,n),0.,1.);" "F=clamp(1.25*g.w-.4,0.,1.);" "F=F*F*.5+.5*F;" diff --git a/tests/real/slisesix.frag.expected b/tests/real/slisesix.frag.expected index abb368dd..2dd0cdad 100644 --- a/tests/real/slisesix.frag.expected +++ b/tests/real/slisesix.frag.expected @@ -30,7 +30,7 @@ float techo(float x,float y) y=1.-y; if(x<.1||x>.9) return y; - x=x-.5; + x-=.5; return-(sqrt(x*x+y*y)-.4); } float distToBox(vec3 p,vec3 abc) @@ -190,7 +190,7 @@ void main() lig=vec3(.5-pos.x,.8-pos.y,1.5-pos.z); llig=dot(lig,lig); im=inversesqrt(llig); - lig=lig*im; + lig*=im; dif=dot(nor,lig); if(matID==4) dif=.5+.5*dif; @@ -264,7 +264,7 @@ void main() } dif*=clamp((so-.4)*1.5,0.,1.); rgb=vec3(spe)+rgb*(ao*vec3(.25,.3,.35)+dif*vec3(1.95,1.65,1.05)); - rgb=rgb*exp2(-.4*t); + rgb*=exp2(-.4*t); } rgb=(sqrt(rgb)*.7+.3*rgb)*vec3(.83,1,.83)*1.2; rgb*=.25+.75*clamp(.6*abs(pixel.x-1.)*abs(pixel.x+1.),0.,1.); diff --git a/tests/real/terrarium.frag.expected b/tests/real/terrarium.frag.expected index 315add74..bd27e1af 100644 --- a/tests/real/terrarium.frag.expected +++ b/tests/real/terrarium.frag.expected @@ -10,19 +10,19 @@ float time=float(m)/44100.; int IH(int a) { a=a^61^a>>16; - a=a+(a<<3); - a=a^a>>4; - a=a*668265261; - a=a^a>>15; + a+=a<<3; + a^=a>>4; + a*=668265261; + a^=a>>15; return a; } float H(int a) { a=a^61^a>>16; - a=a+(a<<3); - a=a^a>>4; - a=a*668265261; - a=a^a>>15; + a+=a<<3; + a^=a>>4; + a*=668265261; + a^=a>>15; return float(a)/2147483647; } vec2 rand2(int a) @@ -131,7 +131,7 @@ void main() u=sqrt(1-u*u); x=vec3(cos(phi)*u,sin(phi)*u,w.y*2-1)*pow(w.z,1./3)*3; q=mix(q,q+x*.5,.1*pow(H(seed),16.)); - q=q+x*.2*(1.-min(time/30.,1.)+max(0.,time-130)/20.); + q+=x*.2*(1.-min(time/30.,1.)+max(0.,time-130)/20.); u=time/8.+199.*step(.5,H(int(floor(time/60.*64.))))*step(60.,time)*step(time,120); q.xy=mat2(cos(u),sin(u),-sin(u),cos(u))*q.xy; u=.4+time/9.; diff --git a/tests/real/the_real_party_is_in_your_pocket.frag.expected b/tests/real/the_real_party_is_in_your_pocket.frag.expected index a7ca9e23..09739df3 100644 --- a/tests/real/the_real_party_is_in_your_pocket.frag.expected +++ b/tests/real/the_real_party_is_in_your_pocket.frag.expected @@ -288,7 +288,7 @@ const char *the_real_party_is_in_your_pocket_frag = "break;" "k=.02;" "if(m()>k)" - "l=c-z*2e-4*-sign(v.z),v=v+(vec3(m(),m(),m())-.5)*.1;" + "l=c-z*2e-4*-sign(v.z),v+=(vec3(m(),m(),m())-.5)*.1;" "else" " l=c+z*2e-4,v=reflect(v,z)+(vec3(m(),m(),m())-.5)*.3;" "}" diff --git a/tests/unit/augmented.frag b/tests/unit/augmented.frag new file mode 100644 index 00000000..6c5366a7 --- /dev/null +++ b/tests/unit/augmented.frag @@ -0,0 +1,13 @@ +int foo(int x, int y) { + int a=x; + a=a+x; + a=a*y; + a=a>>x; + a=a^y; + a=a|y; + return a; +} + +void main() { + foo(0, 0); +} diff --git a/tests/unit/augmented.frag.expected b/tests/unit/augmented.frag.expected new file mode 100644 index 00000000..a8be711d --- /dev/null +++ b/tests/unit/augmented.frag.expected @@ -0,0 +1,14 @@ +int foo(int x,int y) +{ + int a=x; + a+=x; + a*=y; + a>>=x; + a^=y; + a|=y; + return a; +} +void main() +{ + foo(0,0); +}