From a303ef2066e3b60410919e864213adbff856fbe6 Mon Sep 17 00:00:00 2001 From: Sei Lisa Date: Thu, 31 Jul 2014 18:44:50 +0200 Subject: [PATCH] Unfold all assignment+operation operators to optimize them better. With test case. --- lslopt/lsloptimizer.py | 31 +++++++++++++++++++++++-------- testparser.py | 22 ++++++++++++---------- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/lslopt/lsloptimizer.py b/lslopt/lsloptimizer.py index cb025f9..8034707 100644 --- a/lslopt/lsloptimizer.py +++ b/lslopt/lsloptimizer.py @@ -343,8 +343,8 @@ class optimizer(object): else: # x << 0 --> x parent[index] = child[0] else: - pass # TODO: Eliminate redundancy (x+0, x*1, x*-1, v+ZERO_VECTOR, perhaps x-1=~-x, etc.) - # Include != to ^ and || to | and maybe && to & + pass # TODO: Eliminate redundancy (x*1, x*-1, x|0, x&-1, etc.) + # Include != to ^ and || to | and maybe && to & # Note some cases e.g. x*0 can't be optimized away without side-effect analysis. # But some cases like %1 can be turned into *0 to save bytes. # Turn also % (power of 2) into & mask (oops, nope, negative doesn't work) @@ -352,12 +352,27 @@ class optimizer(object): return if nt in self.assign_ops: - # TODO: Eliminate redundant operations, e.g. a += 0; etc. - # Consider also e.g. x -= 1 or x -= a transforming it into +=. - # Actually just consider transforming the whole thing into a - # regular assignment, as there are no gains and it simplifies the - # optimization. - self.FoldTree(child, 1) + # Transform the whole thing into a regular assignment, as there are + # no gains and it simplifies the optimization. + + if nt != '=': + # Replace the node with the expression alone + child[1] = {'nt':'()', 't':child[1]['t'], 'ch':[child[1]]} + node['nt'] = nt[:-1] + + # Linden Craziness: i += f; is valid (but not i -= f). It's + # actually performed as i = (integer)(i + (f)). This breaks + # regular equivalence of x op= y as x = x op (y) so we add + # the type cast here. + if nt == '*=' and child[0]['t'] == 'integer' and child[1]['t'] == 'float': + node['t'] = 'float' # Addition returns float. + node = self.Cast(node, 'integer') + + # And wrap it in an assignment. + node = parent[index] = {'nt':'=', 't':child[0]['t'], 'ch':[child[0].copy(), node]} + + # We have a regular assignment either way now. Simplify the RHS. + self.FoldTree(node['ch'], 1) return if nt == 'IDENT' or nt == 'FLD': diff --git a/testparser.py b/testparser.py index 2b9199c..96f28a9 100644 --- a/testparser.py +++ b/testparser.py @@ -199,16 +199,17 @@ class Test02_Compiler(UnitTestCase): string s = "1" "2"; list L = [(key)""]; default{timer(){ - 1+([]+(integer)~1); - list a; - float f; - a = 3; a += 3; - f += 4; f += -4.3; - integer i; - i |= i; - "a" "b" "c"; - "a"+(key)"b"; (key)"a" + "b"; - i>>=i; + 1+([]+(integer)~1); + list a; + float f; + a = 3; a += 3; + f += 4; f += -4.3; + integer i; + i *= 1.3; + i |= i; + "a" "b" "c"; + "a"+(key)"b"; (key)"a" + "b"; + i>>=i; }}''', ['explicitcast','extendedtypecast','extendedassignment', 'extendedglobalexpr', 'allowmultistrings', 'allowkeyconcat', @@ -264,6 +265,7 @@ class Test03_Optimizer(UnitTestCase): f += 4; f += -4.3; integer i; i = llGetListLength(L); + i *= -3.0; print(3+2); for(i=3,i;1;){} i |= !i;