Skip to content

Commit

Permalink
compress arithmetic expressions further (#3529)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexlamsl committed Oct 26, 2019
1 parent 85237b0 commit 50a578c
Show file tree
Hide file tree
Showing 3 changed files with 432 additions and 75 deletions.
152 changes: 83 additions & 69 deletions lib/compress.js
Expand Up @@ -2437,9 +2437,10 @@ merge(Compressor.prototype, {
|| this.operator == "=" && this.right.is_number(compressor);
});
def(AST_Binary, function(compressor) {
return binary[this.operator] || this.operator == "+"
&& this.left.is_number(compressor)
&& this.right.is_number(compressor);
if (binary[this.operator]) return true;
if (this.operator != "+") return false;
return (this.left.is_boolean(compressor) || this.left.is_number(compressor))
&& (this.right.is_boolean(compressor) || this.right.is_number(compressor));
});
var fn = makePredicate([
"charCodeAt",
Expand Down Expand Up @@ -5777,6 +5778,7 @@ merge(Compressor.prototype, {
}
}
if (compressor.option("evaluate")) {
var associative = true;
switch (self.operator) {
case "&&":
var ll = fuzzy_eval(self.left);
Expand Down Expand Up @@ -5845,9 +5847,6 @@ merge(Compressor.prototype, {
}).optimize(compressor);
}
break;
}
var associative = true;
switch (self.operator) {
case "+":
// "foo" + ("bar" + x) => "foobar" + x
if (self.left instanceof AST_Constant
Expand Down Expand Up @@ -5927,13 +5926,38 @@ merge(Compressor.prototype, {
});
break;
}
case "-":
// a - -b => a + b
if (self.right instanceof AST_UnaryPrefix
&& self.right.operator == "-"
&& self.left.is_number(compressor)) {
self = make_node(AST_Binary, self, {
operator: "+",
left: self.left,
right: self.right.expression
});
break;
}
case "*":
case "/":
associative = compressor.option("unsafe_math");
// +a - b => a - b
// a - +b => a - b
if (self.operator != "+") {
if (self.left instanceof AST_UnaryPrefix && self.left.operator == "+") {
self.left = self.left.expression;
}
if (self.right instanceof AST_UnaryPrefix && self.right.operator == "+") {
self.right = self.right.expression;
}
}
case "&":
case "|":
case "^":
// a + +b => +b + a
if (self.left.is_number(compressor)
if (self.operator != "-"
&& self.operator != "/"
&& self.left.is_number(compressor)
&& self.right.is_number(compressor)
&& reversible()
&& !(self.left instanceof AST_Binary
Expand All @@ -5951,77 +5975,56 @@ merge(Compressor.prototype, {
self = best_of(compressor, self, reversed);
}
}
if (associative && self.is_number(compressor)) {
// a + (b + c) => (a + b) + c
if (self.right instanceof AST_Binary
&& self.right.operator == self.operator) {
self = make_node(AST_Binary, self, {
if (!associative || !self.is_number(compressor)) break;
// a + (b + c) => (a + b) + c
if (self.right instanceof AST_Binary
&& self.right.operator != "%"
&& PRECEDENCE[self.right.operator] == PRECEDENCE[self.operator]) {
self = make_node(AST_Binary, self, {
operator: align(self.operator, self.right.operator),
left: make_node(AST_Binary, self.left, {
operator: self.operator,
left: self.left,
right: self.right.left,
start: self.left.start,
end: self.right.left.end
}),
right: self.right.right
});
}
// (2 * n) * 3 => 6 * n
// (n + 2) + 3 => n + 5
if (self.right instanceof AST_Constant
&& self.left instanceof AST_Binary
&& self.left.operator != "%"
&& PRECEDENCE[self.left.operator] == PRECEDENCE[self.operator]) {
if (self.left.left instanceof AST_Constant) {
self = make_node(AST_Binary, self, {
operator: self.left.operator,
left: make_node(AST_Binary, self.left, {
operator: self.operator,
left: self.left,
right: self.right.left,
start: self.left.start,
end: self.right.left.end
left: self.left.left,
right: self.right,
start: self.left.left.start,
end: self.right.end
}),
right: self.right.right
right: self.left.right
});
}
// (n + 2) + 3 => 5 + n
// (2 * n) * 3 => 6 + n
if (self.right instanceof AST_Constant
&& self.left instanceof AST_Binary
&& self.left.operator == self.operator) {
if (self.left.left instanceof AST_Constant) {
self = make_node(AST_Binary, self, {
operator: self.operator,
left: make_node(AST_Binary, self.left, {
operator: self.operator,
left: self.left.left,
right: self.right,
start: self.left.left.start,
end: self.right.end
}),
right: self.left.right
});
} else if (self.left.right instanceof AST_Constant) {
self = make_node(AST_Binary, self, {
operator: self.operator,
left: make_node(AST_Binary, self.left, {
operator: self.operator,
left: self.left.right,
right: self.right,
start: self.left.right.start,
end: self.right.end
}),
right: self.left.left
});
}
}
// (a | 1) | (2 | d) => (3 | a) | b
if (self.left instanceof AST_Binary
&& self.left.operator == self.operator
&& self.left.right instanceof AST_Constant
&& self.right instanceof AST_Binary
&& self.right.operator == self.operator
&& self.right.left instanceof AST_Constant) {
} else if (self.left.right instanceof AST_Constant) {
self = make_node(AST_Binary, self, {
operator: self.operator,
left: make_node(AST_Binary, self.left, {
operator: self.operator,
left: make_node(AST_Binary, self.left.left, {
operator: self.operator,
left: self.left.right,
right: self.right.left,
start: self.left.right.start,
end: self.right.left.end
}),
right: self.left.left
}),
right: self.right.right
operator: self.left.operator,
left: self.left.left,
right: make_node(AST_Binary, self.left, {
operator: align(self.left.operator, self.operator),
left: self.left.right,
right: self.right,
start: self.left.right.start,
end: self.right.end
})
});
}
}
break;
}
}
if (compressor.option("unsafe")) {
Expand Down Expand Up @@ -6086,6 +6089,17 @@ merge(Compressor.prototype, {
}
return self;

function align(ref, op) {
switch (ref) {
case "-":
return op == "+" ? "-" : "+";
case "/":
return op == "*" ? "/" : "*";
default:
return op;
}
}

function fuzzy_eval(node) {
if (node.truthy) return true;
if (node.falsy) return false;
Expand Down
2 changes: 1 addition & 1 deletion test/compress/asm.js
Expand Up @@ -96,7 +96,7 @@ asm_mixed: {
return +sum;
}
function geometricMean(start, end) {
return start |= 0, end |= 0, +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 };
Expand Down

0 comments on commit 50a578c

Please sign in to comment.