Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(881)

Unified Diff: lib/src/compiler/code_generator.dart

Issue 1950583002: Further bitop optimizations (Closed) Base URL: https://github.com/dart-lang/dev_compiler@master
Patch Set: rebase Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « lib/runtime/dart_sdk.js ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/src/compiler/code_generator.dart
diff --git a/lib/src/compiler/code_generator.dart b/lib/src/compiler/code_generator.dart
index d9c127178cbf837ce80dbeb56ab95f998d8c178a..8a54e168c504c7569bd11e5ef59fd9ad217282b2 100644
--- a/lib/src/compiler/code_generator.dart
+++ b/lib/src/compiler/code_generator.dart
@@ -3346,9 +3346,12 @@ class CodeGenerator extends GeneralizingAstVisitor
if (_isDefinitelyNonNegative(left) && shiftCount != null) {
return binary('# >>> #');
}
- // TODO(sra): If the context selects out only bits that can't be
- // affected by the sign position we can use any JavaScript shift.
- // E.g. `(x >> 6) & 3`.
+ // If the context selects out only bits that can't be affected by the
+ // sign position we can use any JavaScript shift, `(x >> 6) & 3`.
+ if (shiftCount != null &&
+ _parentMasksToWidth(node, 31 - shiftCount)) {
+ return binary('# >> #');
+ }
return _emitSend(left, op.lexeme, [right]);
case TokenType.LT_LT:
@@ -3376,18 +3379,34 @@ class CodeGenerator extends GeneralizingAstVisitor
/// JavaScript operations interpret their operands as signed and generate
/// signed results.
JS.Expression _coerceBitOperationResultToUnsigned(
- Expression node, JS.Expression operation) {
+ Expression node, JS.Expression uncoerced) {
// Don't coerce if the parent will coerce.
AstNode parent = _parentOperation(node);
- if (_nodeIsBitwiseOperation(parent)) return operation;
+ if (_nodeIsBitwiseOperation(parent)) return uncoerced;
// Don't do a no-op coerce if the most significant bit is zero.
- if (_is31BitUnsigned(node)) return operation;
-
- // TODO(sra): If the consumer of the expression is '==' or '!=' to a
- // constant that fits in 31 bits, adding a coercion does not change the
- // result of the comparision, e.g. `a & ~b == 0`.
- return js.call('# >>> 0', operation);
+ if (_is31BitUnsigned(node)) return uncoerced;
+
+ // If the consumer of the expression is '==' or '!=' with a constant that
+ // fits in 31 bits, adding a coercion does not change the result of the
+ // comparision, e.g. `a & ~b == 0`.
+ if (parent is BinaryExpression) {
+ var tokenType = parent.operator.type;
+ Expression left = parent.leftOperand;
+ Expression right = parent.rightOperand;
+ if (tokenType == TokenType.EQ_EQ || tokenType == TokenType.BANG_EQ) {
+ const int MAX = 0x7fffffff;
+ if (_asIntInRange(right, 0, MAX) != null) return uncoerced;
+ if (_asIntInRange(left, 0, MAX) != null) return uncoerced;
+ } else if (tokenType == TokenType.GT_GT) {
+ if (_isDefinitelyNonNegative(left) &&
+ _asIntInRange(right, 0, 31) != null) {
+ // Parent will generate `# >>> n`.
+ return uncoerced;
+ }
+ }
+ }
+ return js.call('# >>> 0', uncoerced);
}
AstNode _parentOperation(AstNode node) {
@@ -3412,24 +3431,31 @@ class CodeGenerator extends GeneralizingAstVisitor
return false;
}
- Expression _skipParentheses(Expression expr) {
- while (expr is ParenthesizedExpression) {
- ParenthesizedExpression parenExpr = expr;
- expr = parenExpr.expression;
- }
- return expr;
- }
-
int _asIntInRange(Expression expr, int low, int high) {
- expr = _skipParentheses(expr);
+ expr = expr.unParenthesized;
if (expr is IntegerLiteral) {
if (expr.value >= low && expr.value <= high) return expr.value;
+ return null;
+ }
+ int finishIdentifier(SimpleIdentifier identifier) {
+ Element staticElement = identifier.staticElement;
+ if (staticElement is PropertyAccessorElement && staticElement.isGetter) {
+ PropertyInducingElement variable = staticElement.variable;
+ int value = variable?.constantValue?.toIntValue();
+ if (value != null && value >= low && value <= high) return value;
+ }
+ return null;
+ }
+ if (expr is SimpleIdentifier) {
+ return finishIdentifier(expr);
+ } else if (expr is PrefixedIdentifier && !expr.isDeferred) {
+ return finishIdentifier(expr.identifier);
}
return null;
}
bool _isDefinitelyNonNegative(Expression expr) {
- expr = _skipParentheses(expr);
+ expr = expr.unParenthesized;
if (expr is IntegerLiteral) {
return expr.value >= 0;
}
@@ -3438,6 +3464,24 @@ class CodeGenerator extends GeneralizingAstVisitor
return false;
}
+ /// Does the parent of [node] mask the result to [width] bits or fewer?
+ bool _parentMasksToWidth(AstNode node, int width) {
+ AstNode parent = _parentOperation(node);
+ if (parent == null) return false;
+ if (_nodeIsBitwiseOperation(parent)) {
+ if (parent is BinaryExpression &&
+ parent.operator.type == TokenType.AMPERSAND) {
+ Expression left = parent.leftOperand;
+ Expression right = parent.rightOperand;
+ final int MAX = (1 << width) - 1;
+ if (_asIntInRange(right, 0, MAX) != null) return true;
+ if (_asIntInRange(left, 0, MAX) != null) return true;
+ }
+ return _parentMasksToWidth(parent, width);
+ }
+ return false;
+ }
+
/// Determines if the result of evaluating [expr] will be an non-negative
/// value that fits in 31 bits.
bool _is31BitUnsigned(Expression expr) {
@@ -3450,8 +3494,8 @@ class CodeGenerator extends GeneralizingAstVisitor
}
if (++depth > 5) return MAX;
if (expr is BinaryExpression) {
- var left = _skipParentheses(expr.leftOperand);
- var right = _skipParentheses(expr.rightOperand);
+ var left = expr.leftOperand.unParenthesized;
+ var right = expr.rightOperand.unParenthesized;
switch (expr.operator.type) {
case TokenType.AMPERSAND:
return min(bitWidth(left, depth), bitWidth(right, depth));
@@ -3485,6 +3529,8 @@ class CodeGenerator extends GeneralizingAstVisitor
return MAX;
}
}
+ int value = _asIntInRange(expr, 0, 0x7fffffff);
+ if (value != null) return value.bitLength;
return MAX;
}
return bitWidth(expr, 0) < 32;
« no previous file with comments | « lib/runtime/dart_sdk.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698