Implement inlining heuristics on conditional expression.

Change-Id: I183b6345e29d6c00f140dcbd1ffff05faf0e781f
Reviewed-on: https://dart-review.googlesource.com/30442
Reviewed-by: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
Johnni Winther 2017-12-20 08:02:14 +00:00
parent 72736aff0d
commit 12ee4edbb8
2 changed files with 105 additions and 0 deletions

View file

@ -4838,6 +4838,7 @@ class InlineWeeder extends ir.Visitor {
return true;
}
@override
defaultNode(ir.Node node) {
if (tooDifficult) return;
if (!registerNode()) return;
@ -4848,6 +4849,7 @@ class InlineWeeder extends ir.Visitor {
node.visitChildren(this);
}
@override
visitReturnStatement(ir.ReturnStatement node) {
if (!registerNode()) return;
if (seenReturn) {
@ -4858,6 +4860,7 @@ class InlineWeeder extends ir.Visitor {
seenReturn = true;
}
@override
visitThrow(ir.Throw node) {
if (!registerNode()) return;
if (seenReturn) {
@ -4876,42 +4879,51 @@ class InlineWeeder extends ir.Visitor {
// isn't in the AST based inline weeder.
}
@override
visitForStatement(ir.ForStatement node) {
_handleLoop();
}
@override
visitForInStatement(ir.ForInStatement node) {
_handleLoop();
}
@override
visitWhileStatement(ir.WhileStatement node) {
_handleLoop();
}
@override
visitDoStatement(ir.DoStatement node) {
_handleLoop();
}
@override
visitTryCatch(ir.TryCatch node) {
if (tooDifficult) return;
tooDifficultReason = 'try';
}
@override
visitTryFinally(ir.TryFinally node) {
if (tooDifficult) return;
tooDifficultReason = 'try';
}
@override
visitFunctionExpression(ir.FunctionExpression node) {
if (!registerNode()) return;
tooDifficultReason = 'closure';
}
@override
visitFunctionDeclaration(ir.FunctionDeclaration node) {
if (!registerNode()) return;
tooDifficultReason = 'closure';
}
@override
visitFunctionNode(ir.FunctionNode node) {
if (node.asyncMarker != ir.AsyncMarker.Sync) {
tooDifficultReason = 'async/await';
@ -4919,6 +4931,36 @@ class InlineWeeder extends ir.Visitor {
}
node.visitChildren(this);
}
@override
visitConditionalExpression(ir.ConditionalExpression node) {
// Heuristic: In "parameter ? A : B" there is a high probability that
// parameter is a constant. Assuming the parameter is constant, we can
// compute a count that is bounded by the largest arm rather than the sum of
// both arms.
ir.Expression condition = node.condition;
condition.accept(this);
if (tooDifficult) return;
int commonPrefixCount = nodeCount;
node.then.accept(this);
if (tooDifficult) return;
int thenCount = nodeCount - commonPrefixCount;
nodeCount = commonPrefixCount;
node.otherwise.accept(this);
if (tooDifficult) return;
int elseCount = nodeCount - commonPrefixCount;
nodeCount = commonPrefixCount + thenCount + elseCount;
if (condition is ir.VariableGet &&
condition.variable.parent is ir.FunctionNode) {
nodeCount =
commonPrefixCount + (thenCount > elseCount ? thenCount : elseCount);
}
// This is last so that [tooDifficult] is always updated.
if (!registerNode()) return;
}
}
/// Class in charge of building try, catch and/or finally blocks. This handles

View file

@ -0,0 +1,63 @@
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Tests for the heuristics on conditional expression whose condition is a
// parameter for which the max, instead of the sum, of the branch sizes is used.
// ignore: IMPORT_INTERNAL_LIBRARY
import 'dart:_js_helper';
/*element: main:[]*/
main() {
conditionalField();
conditionalParameter();
}
////////////////////////////////////////////////////////////////////////////////
// Conditional expression on a non-parameter (here a top-level field). The
// size of the condition is the sum of the nodes in the conditional expression.
////////////////////////////////////////////////////////////////////////////////
/*element: _method1:[_conditionalField]*/
_method1() => 42;
var _field1;
/*element: _conditionalField:[]*/
_conditionalField() {
return _field1
? _method1() + _method1() + _method1()
: _method1() + _method1() + _method1();
}
/*element: conditionalField:[]*/
@NoInline()
conditionalField() {
_field1 = false;
_conditionalField();
_field1 = true;
_conditionalField();
}
////////////////////////////////////////////////////////////////////////////////
// Conditional expression on a parameter. The size of the condition is the
// max of the branches + the condition itself.
////////////////////////////////////////////////////////////////////////////////
/*element: _method2:[conditionalParameter]*/
_method2() => 42;
/*element: _conditionalParameter:[conditionalParameter]*/
_conditionalParameter(o) {
return o
? _method2() + _method2() + _method2()
: _method2() + _method2() + _method2();
}
/*element: conditionalParameter:[]*/
@NoInline()
conditionalParameter() {
_conditionalParameter(true);
_conditionalParameter(false);
}