From: kzc Date: Fri, 26 Aug 2016 22:47:25 +0000 (-0400) Subject: implement optimization: (x = 2 * x) ---> (x *= 2) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=0bd8053524760531eb582ef0716fcfe2104c3014;p=UglifyJS.git implement optimization: (x = 2 * x) ---> (x *= 2) --- diff --git a/lib/compress.js b/lib/compress.js index f8d9d329..8f786d73 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -2655,16 +2655,26 @@ merge(Compressor.prototype, { }); var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ]; + var ASSIGN_OPS_COMMUTATIVE = [ '*', '|', '^', '&' ]; OPT(AST_Assign, function(self, compressor){ self = self.lift_sequences(compressor); - if (self.operator == "=" - && self.left instanceof AST_SymbolRef - && self.right instanceof AST_Binary - && self.right.left instanceof AST_SymbolRef - && self.right.left.name == self.left.name - && member(self.right.operator, ASSIGN_OPS)) { - self.operator = self.right.operator + "="; - self.right = self.right.right; + if (self.operator == "=" && self.left instanceof AST_SymbolRef && self.right instanceof AST_Binary) { + // x = expr1 OP expr2 + if (self.right.left instanceof AST_SymbolRef + && self.right.left.name == self.left.name + && member(self.right.operator, ASSIGN_OPS)) { + // x = x - 2 ---> x -= 2 + self.operator = self.right.operator + "="; + self.right = self.right.right; + } + else if (self.right.right instanceof AST_SymbolRef + && self.right.right.name == self.left.name + && member(self.right.operator, ASSIGN_OPS_COMMUTATIVE) + && !self.right.left.has_side_effects(compressor)) { + // x = 2 & x ---> x &= 2 + self.operator = self.right.operator + "="; + self.right = self.right.left; + } } return self; }); diff --git a/test/compress/asm.js b/test/compress/asm.js index f392e78e..9b227326 100644 --- a/test/compress/asm.js +++ b/test/compress/asm.js @@ -90,13 +90,13 @@ asm_mixed: { } function no_asm_GeometricMean(stdlib, foreign, buffer) { function logSum(start, end) { - start = 0 | start, end = 0 | end; + start |= 0, end |= 0; var sum = 0, p = 0, q = 0; for (p = start << 3, q = end << 3; (0 | p) < (0 | q); p = p + 8 | 0) sum += +log(values[p >> 3]); return +sum; } function geometricMean(start, end) { - return start = 0 | start, end = 0 | end, +exp(+logSum(start, end) / +(end - start | 0)); + return start |= 0, end |= 0, +exp(+logSum(start, end) / +(end - start | 0)); } var exp = stdlib.Math.exp, log = stdlib.Math.log, values = new stdlib.Float64Array(buffer); return { geometricMean: geometricMean }; diff --git a/test/compress/assignment.js b/test/compress/assignment.js new file mode 100644 index 00000000..903380a9 --- /dev/null +++ b/test/compress/assignment.js @@ -0,0 +1,238 @@ +op_equals_left_local_var: { + options = { + evaluate: true, + } + input: { + var x; + + x = x + 3; + x = x - 3; + x = x / 3; + x = x * 3; + x = x >> 3; + x = x << 3; + x = x >>> 3; + x = x | 3; + x = x ^ 3; + x = x % 3; + x = x & 3; + + x = x + g(); + x = x - g(); + x = x / g(); + x = x * g(); + x = x >> g(); + x = x << g(); + x = x >>> g(); + x = x | g(); + x = x ^ g(); + x = x % g(); + x = x & g(); + } + expect: { + var x; + + x += 3; + x -= 3; + x /= 3; + x *= 3; + x >>= 3; + x <<= 3; + x >>>= 3; + x |= 3; + x ^= 3; + x %= 3; + x &= 3; + + x += g(); + x -= g(); + x /= g(); + x *= g(); + x >>= g(); + x <<= g(); + x >>>= g(); + x |= g(); + x ^= g(); + x %= g(); + x &= g(); + } +} + +op_equals_right_local_var: { + options = { + evaluate: true, + } + input: { + var x; + + x = (x -= 2) ^ x; + + x = 3 + x; + x = 3 - x; + x = 3 / x; + x = 3 * x; + x = 3 >> x; + x = 3 << x; + x = 3 >>> x; + x = 3 | x; + x = 3 ^ x; + x = 3 % x; + x = 3 & x; + + x = g() + x; + x = g() - x; + x = g() / x; + x = g() * x; + x = g() >> x; + x = g() << x; + x = g() >>> x; + x = g() | x; + x = g() ^ x; + x = g() % x; + x = g() & x; + } + expect: { + var x; + + x = (x -= 2) ^ x; + + x = 3 + x; + x = 3 - x; + x = 3 / x; + x *= 3; + x = 3 >> x; + x = 3 << x; + x = 3 >>> x; + x |= 3; + x ^= 3; + x = 3 % x; + x &= 3; + + x = g() + x; + x = g() - x; + x = g() / x; + x = g() * x; + x = g() >> x; + x = g() << x; + x = g() >>> x; + x = g() | x; + x = g() ^ x; + x = g() % x; + x = g() & x; + } +} +op_equals_left_global_var: { + options = { + evaluate: true, + } + input: { + x = x + 3; + x = x - 3; + x = x / 3; + x = x * 3; + x = x >> 3; + x = x << 3; + x = x >>> 3; + x = x | 3; + x = x ^ 3; + x = x % 3; + x = x & 3; + + x = x + g(); + x = x - g(); + x = x / g(); + x = x * g(); + x = x >> g(); + x = x << g(); + x = x >>> g(); + x = x | g(); + x = x ^ g(); + x = x % g(); + x = x & g(); + } + expect: { + x += 3; + x -= 3; + x /= 3; + x *= 3; + x >>= 3; + x <<= 3; + x >>>= 3; + x |= 3; + x ^= 3; + x %= 3; + x &= 3; + + x += g(); + x -= g(); + x /= g(); + x *= g(); + x >>= g(); + x <<= g(); + x >>>= g(); + x |= g(); + x ^= g(); + x %= g(); + x &= g(); + } +} + +op_equals_right_global_var: { + options = { + evaluate: true, + } + input: { + x = (x -= 2) ^ x; + + x = 3 + x; + x = 3 - x; + x = 3 / x; + x = 3 * x; + x = 3 >> x; + x = 3 << x; + x = 3 >>> x; + x = 3 | x; + x = 3 ^ x; + x = 3 % x; + x = 3 & x; + + x = g() + x; + x = g() - x; + x = g() / x; + x = g() * x; + x = g() >> x; + x = g() << x; + x = g() >>> x; + x = g() | x; + x = g() ^ x; + x = g() % x; + x = g() & x; + } + expect: { + x = (x -= 2) ^ x; + + x = 3 + x; + x = 3 - x; + x = 3 / x; + x *= 3; + x = 3 >> x; + x = 3 << x; + x = 3 >>> x; + x |= 3; + x ^= 3; + x = 3 % x; + x &= 3; + + x = g() + x; + x = g() - x; + x = g() / x; + x = g() * x; + x = g() >> x; + x = g() << x; + x = g() >>> x; + x = g() | x; + x = g() ^ x; + x = g() % x; + x = g() & x; + } +}