enhance conditionals & switches (#4058)

This commit is contained in:
Alex Lam S.L
2020-08-20 17:35:39 +01:00
committed by GitHub
parent 1c6384b6a5
commit a153176469
3 changed files with 189 additions and 24 deletions

View File

@@ -5916,28 +5916,57 @@ merge(Compressor.prototype, {
} }
body[0].body = decl.concat(body[0].body); body[0].body = decl.concat(body[0].body);
self.body = body; self.body = body;
if (body.length == 1 && (body[0] === exact_match || body[0] === default_branch)) { if (compressor.option("conditionals")) switch (body.length) {
var has_break = false; case 1:
var tw = new TreeWalker(function(node) { if (!no_break(self)) break;
if (has_break var exp = body[0].expression;
|| node instanceof AST_Lambda var statements = body[0].body.slice();
|| node instanceof AST_SimpleStatement) return true; if (body[0] !== default_branch && body[0] !== exact_match) return make_node(AST_If, self, {
if (is_break(node, tw)) has_break = true; condition: make_node(AST_Binary, self, {
operator: "===",
left: self.expression,
right: exp,
}),
body: make_node(AST_BlockStatement, self, {
body: statements,
}),
alternative: null,
}).optimize(compressor);
if (exp) statements.unshift(make_node(AST_SimpleStatement, exp, {
body: exp,
}));
statements.unshift(make_node(AST_SimpleStatement, self.expression, {
body:self.expression,
}));
return make_node(AST_BlockStatement, self, {
body: statements,
}).optimize(compressor);
case 2:
if (!member(default_branch, body)) break;
var statements = body[0].body.slice();
var exclusive = statements.length && is_break(statements[statements.length - 1], compressor);
if (exclusive) statements.pop();
if (!all(statements, no_break)) break;
var alternative = body[1].body.length && make_node(AST_BlockStatement, body[1], body[1]);
var node = make_node(AST_If, self, {
condition: make_node(AST_Binary, self, body[0] === default_branch ? {
operator: "!==",
left: self.expression,
right: body[1].expression,
} : {
operator: "===",
left: self.expression,
right: body[0].expression,
}),
body: make_node(AST_BlockStatement, body[0], {
body: statements,
}),
alternative: exclusive && alternative || null,
}); });
self.walk(tw); if (!exclusive && alternative) node = make_node(AST_BlockStatement, self, {
if (!has_break) { body: [ node, alternative ],
var statements = body[0].body.slice(); });
var exp = body[0].expression; return node.optimize(compressor);
if (exp) statements.unshift(make_node(AST_SimpleStatement, exp, {
body: exp
}));
statements.unshift(make_node(AST_SimpleStatement, self.expression, {
body:self.expression
}));
return make_node(AST_BlockStatement, self, {
body: statements
}).optimize(compressor);
}
} }
return self; return self;
@@ -5945,6 +5974,18 @@ merge(Compressor.prototype, {
return node instanceof AST_Break && tw.loopcontrol_target(node) === self; return node instanceof AST_Break && tw.loopcontrol_target(node) === self;
} }
function no_break(node) {
var found = false;
var tw = new TreeWalker(function(node) {
if (found
|| node instanceof AST_Lambda
|| node instanceof AST_SimpleStatement) return true;
if (is_break(node, tw)) found = true;
});
node.walk(tw);
return !found;
}
function eliminate_branch(branch, prev) { function eliminate_branch(branch, prev) {
if (prev && !aborts(prev)) { if (prev && !aborts(prev)) {
prev.body = prev.body.concat(branch.body); prev.body = prev.body.concat(branch.body);

View File

@@ -2031,6 +2031,7 @@ issue_1670_4: {
issue_1670_5: { issue_1670_5: {
options = { options = {
conditionals: true,
dead_code: true, dead_code: true,
evaluate: true, evaluate: true,
keep_fargs: false, keep_fargs: false,
@@ -2062,6 +2063,7 @@ issue_1670_5: {
issue_1670_6: { issue_1670_6: {
options = { options = {
conditionals: true,
dead_code: true, dead_code: true,
evaluate: true, evaluate: true,
keep_fargs: false, keep_fargs: false,

View File

@@ -1,5 +1,6 @@
constant_switch_1: { constant_switch_1: {
options = { options = {
conditionals: true,
dead_code: true, dead_code: true,
evaluate: true, evaluate: true,
side_effects: true, side_effects: true,
@@ -19,6 +20,7 @@ constant_switch_1: {
constant_switch_2: { constant_switch_2: {
options = { options = {
conditionals: true,
dead_code: true, dead_code: true,
evaluate: true, evaluate: true,
side_effects: true, side_effects: true,
@@ -39,6 +41,7 @@ constant_switch_2: {
constant_switch_3: { constant_switch_3: {
options = { options = {
conditionals: true,
dead_code: true, dead_code: true,
evaluate: true, evaluate: true,
side_effects: true, side_effects: true,
@@ -60,6 +63,7 @@ constant_switch_3: {
constant_switch_4: { constant_switch_4: {
options = { options = {
conditionals: true,
dead_code: true, dead_code: true,
evaluate: true, evaluate: true,
side_effects: true, side_effects: true,
@@ -86,6 +90,7 @@ constant_switch_4: {
constant_switch_5: { constant_switch_5: {
options = { options = {
conditionals: true,
dead_code: true, dead_code: true,
evaluate: true, evaluate: true,
side_effects: true, side_effects: true,
@@ -120,6 +125,7 @@ constant_switch_5: {
constant_switch_6: { constant_switch_6: {
options = { options = {
conditionals: true,
dead_code: true, dead_code: true,
evaluate: true, evaluate: true,
side_effects: true, side_effects: true,
@@ -154,6 +160,7 @@ constant_switch_6: {
constant_switch_7: { constant_switch_7: {
options = { options = {
conditionals: true,
dead_code: true, dead_code: true,
evaluate: true, evaluate: true,
side_effects: true, side_effects: true,
@@ -197,6 +204,7 @@ constant_switch_7: {
constant_switch_8: { constant_switch_8: {
options = { options = {
conditionals: true,
dead_code: true, dead_code: true,
evaluate: true, evaluate: true,
side_effects: true, side_effects: true,
@@ -226,6 +234,7 @@ constant_switch_8: {
constant_switch_9: { constant_switch_9: {
options = { options = {
conditionals: true,
dead_code: true, dead_code: true,
evaluate: true, evaluate: true,
side_effects: true, side_effects: true,
@@ -315,6 +324,7 @@ keep_default: {
issue_1663: { issue_1663: {
options = { options = {
conditionals: true,
dead_code: true, dead_code: true,
evaluate: true, evaluate: true,
side_effects: true, side_effects: true,
@@ -551,6 +561,7 @@ issue_441_2: {
issue_1674: { issue_1674: {
options = { options = {
conditionals: true,
dead_code: true, dead_code: true,
evaluate: true, evaluate: true,
side_effects: true, side_effects: true,
@@ -876,6 +887,7 @@ beautify: {
issue_1758: { issue_1758: {
options = { options = {
conditionals: true,
dead_code: true, dead_code: true,
switches: true, switches: true,
} }
@@ -898,15 +910,16 @@ issue_1758: {
issue_2535: { issue_2535: {
options = { options = {
conditionals: true,
dead_code: true, dead_code: true,
evaluate: true, evaluate: true,
switches: true, switches: true,
} }
input: { input: {
switch(w(), 42) { switch(w(), 42) {
case 13: x(); case 13: x();
case 42: y(); case 42: y();
default: z(); default: z();
} }
} }
expect: { expect: {
@@ -919,6 +932,7 @@ issue_2535: {
issue_1750: { issue_1750: {
options = { options = {
conditionals: true,
dead_code: true, dead_code: true,
evaluate: true, evaluate: true,
switches: true, switches: true,
@@ -963,6 +977,7 @@ drop_switch_1: {
drop_switch_2: { drop_switch_2: {
options = { options = {
conditionals: true,
dead_code: true, dead_code: true,
switches: true, switches: true,
} }
@@ -1007,6 +1022,7 @@ drop_switch_3: {
drop_switch_4: { drop_switch_4: {
options = { options = {
conditionals: true,
dead_code: true, dead_code: true,
switches: true, switches: true,
} }
@@ -1028,3 +1044,109 @@ drop_switch_4: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
drop_switch_5: {
options = {
conditionals: true,
dead_code: true,
switches: true,
}
input: {
switch (A) {
case B:
x();
default:
}
switch (C) {
default:
y();
case D:
}
}
expect: {
A === B && x();
C !== D && y();
}
}
drop_switch_6: {
options = {
conditionals: true,
dead_code: true,
switches: true,
}
input: {
switch (A) {
case B:
default:
x();
}
switch (C) {
default:
case D:
y();
}
}
expect: {
A === B;
x();
C !== D;
y();
}
}
drop_switch_7: {
options = {
conditionals: true,
dead_code: true,
switches: true,
}
input: {
switch (A) {
case B:
w();
default:
x();
}
switch (C) {
default:
y();
case D:
z();
}
}
expect: {
A === B && w();
x();
C !== D && y();
z();
}
}
drop_switch_8: {
options = {
conditionals: true,
dead_code: true,
switches: true,
}
input: {
switch (A) {
case B:
w();
break;
default:
x();
}
switch (C) {
default:
y();
break;
case D:
z();
}
}
expect: {
(A === B ? w : x)();
(C !== D ? y : z)();
}
}