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

Side by Side Diff: pkg/compiler/lib/src/cps_ir/bounds_checker.dart

Issue 1479193002: dart2js cps: Add more constraint rules to bounds-check elimination. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years 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 unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dart2js.cps_ir.bounds_checker; 5 library dart2js.cps_ir.bounds_checker;
6 6
7 import 'cps_ir_nodes.dart'; 7 import 'cps_ir_nodes.dart';
8 import 'optimizers.dart' show Pass; 8 import 'optimizers.dart' show Pass;
9 import 'octagon.dart'; 9 import 'octagon.dart';
10 import '../constants/values.dart'; 10 import '../constants/values.dart';
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 void makeGreaterThanOrEqual(SignedVariable v1, SignedVariable v2) { 161 void makeGreaterThanOrEqual(SignedVariable v1, SignedVariable v2) {
162 // v1 >= v2 <==> v2 - v1 <= 0 162 // v1 >= v2 <==> v2 - v1 <= 0
163 applyConstraint(v2, v1.negated, 0); 163 applyConstraint(v2, v1.negated, 0);
164 } 164 }
165 165
166 void makeGreaterThan(SignedVariable v1, SignedVariable v2) { 166 void makeGreaterThan(SignedVariable v1, SignedVariable v2) {
167 // v1 > v2 <==> v2 - v1 <= -1 167 // v1 > v2 <==> v2 - v1 <= -1
168 applyConstraint(v2, v1.negated, -1); 168 applyConstraint(v2, v1.negated, -1);
169 } 169 }
170 170
171 void makeLessThanOrEqualToConstant(SignedVariable v1, int k) {
172 // v1 + v1 <= 2k
173 applyConstraint(v1, v1, 2 * k);
174 }
175
176 void makeGreaterThanOrEqualToConstant(SignedVariable v1, int k) {
177 // -v1 - v1 <= -2k
178 applyConstraint(v1.negated, v1.negated, -2 * k);
179 }
180
171 void makeConstant(SignedVariable v1, int k) { 181 void makeConstant(SignedVariable v1, int k) {
172 // We model this using the constraints: 182 // We model this using the constraints:
173 // v1 + v1 <= 2k 183 // v1 + v1 <= 2k
174 // -v1 - v1 <= -2k 184 // -v1 - v1 <= -2k
175 applyConstraint(v1, v1, 2 * k); 185 applyConstraint(v1, v1, 2 * k);
176 applyConstraint(v1.negated, v1.negated, -2 * k); 186 applyConstraint(v1.negated, v1.negated, -2 * k);
177 } 187 }
178 188
179 /// Make `v1 = v2 + k`. 189 /// Make `v1 = v2 + k`.
180 void makeExactSum(SignedVariable v1, SignedVariable v2, int k) { 190 void makeExactSum(SignedVariable v1, SignedVariable v2, int k) {
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 // TODO(asgerf): It might be faster to inline the constant in the 332 // TODO(asgerf): It might be faster to inline the constant in the
323 // constraints that reference it. 333 // constraints that reference it.
324 if (node.value.isInt) { 334 if (node.value.isInt) {
325 IntConstantValue constant = node.value; 335 IntConstantValue constant = node.value;
326 makeConstant(getValue(node), constant.primitiveValue); 336 makeConstant(getValue(node), constant.primitiveValue);
327 } 337 }
328 } 338 }
329 339
330 @override 340 @override
331 void visitApplyBuiltinOperator(ApplyBuiltinOperator node) { 341 void visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
332 if (node.operator != BuiltinOperator.NumAdd && 342 if (!isInt(node)) return;
333 node.operator != BuiltinOperator.NumSubtract) { 343 if (node.arguments.length == 1) {
334 return; 344 applyUnaryOperator(node);
335 } 345 } else if (node.arguments.length == 2) {
336 if (!isInt(node.arguments[0].definition) || 346 applyBinaryOperator(node);
337 !isInt(node.arguments[1].definition)) {
338 return;
339 }
340 if (!isInt(node)) {
341 // TODO(asgerf): The result of this operation should always be an integer,
342 // but currently type propagation does not always prove this.
343 return;
344 }
345 // We have `v1 = v2 +/- v3`, but the octagon cannot represent constraints
346 // involving more than two variables. Check if one operand is a constant.
347 int getConstantArgument(int n) {
348 Primitive prim = node.arguments[n].definition;
349 if (prim is Constant && prim.value.isInt) {
350 IntConstantValue constant = prim.value;
351 return constant.primitiveValue;
352 }
353 return null;
354 }
355 int constant = getConstantArgument(0);
356 int operandIndex = 1;
357 if (constant == null) {
358 constant = getConstantArgument(1);
359 operandIndex = 0;
360 }
361 if (constant == null) {
362 // Neither argument was a constant.
363 // Classical octagon-based analyzers would compute upper and lower bounds
364 // for the two operands and add constraints for the result based on
365 // those. For performance reasons we omit that.
366 // TODO(asgerf): It seems expensive, but we should evaluate it.
367 return;
368 }
369 SignedVariable v1 = getValue(node);
370 SignedVariable v2 = getValue(node.arguments[operandIndex].definition);
371
372 if (node.operator == BuiltinOperator.NumAdd) {
373 // v1 = v2 + const
374 makeFloatingPointSum(v1, v2, constant);
375 } else if (operandIndex == 0) {
376 // v1 = v2 - const
377 makeFloatingPointSum(v1, v2, -constant);
378 } else {
379 // v1 = const - v2 <==> v1 = (-v2) + const
380 makeFloatingPointSum(v1, v2.negated, constant);
381 } 347 }
382 } 348 }
383 349
350 void applyBinaryOperator(ApplyBuiltinOperator node) {
351 Primitive left = node.arguments[0].definition;
352 Primitive right = node.arguments[1].definition;
353 if (!isInt(left) || !isInt(right)) {
354 return;
355 }
356 SignedVariable leftVar = getValue(left);
357 SignedVariable rightVar = getValue(right);
358 SignedVariable result = getValue(node);
359 switch (node.operator) {
360 case BuiltinOperator.NumAdd:
361 int leftConst = getIntConstant(left);
362 if (leftConst != null) {
363 makeFloatingPointSum(result, rightVar, leftConst);
364 }
365 int rightConst = getIntConstant(right);
366 if (rightConst != null) {
367 makeFloatingPointSum(result, leftVar, rightConst);
368 }
369 // Attempt to compute the sign of the result.
370 // TODO(asgerf): Compute upper/lower bounds instead of using 0.
371 if (testConstraint(leftVar, rightVar, 0)) {
372 makeLessThanOrEqualToConstant(result, 0);
373 }
374 if (testConstraint(leftVar.negated, rightVar.negated, 0)) {
375 makeGreaterThanOrEqualToConstant(result, 0);
376 }
377 // Classical octagon-based analyzers would compute upper and lower
378 // bounds for the two operands and add constraints for the result based
379 // on those. For performance reasons we only compute the sign
380 // TODO(asgerf): It seems expensive, but we should evaluate it.
381 break;
382
383 case BuiltinOperator.NumSubtract:
384 int leftConst = getIntConstant(left);
385 if (leftConst != null) {
386 // result = leftConst - right = (-right) + leftConst
387 makeFloatingPointSum(result, rightVar.negated, leftConst);
388 }
389 int rightConst = getIntConstant(right);
390 if (rightConst != null) {
391 // result = left - rightConst = left + (-rightConst)
392 makeFloatingPointSum(result, leftVar, -rightConst);
393 }
394 // Attempt to compute the sign of the result.
395 if (isDefinitelyGreaterThanOrEqualTo(leftVar, rightVar)) {
396 makeGreaterThanOrEqualToConstant(result, 0);
397 }
398 if (isDefinitelyLessThanOrEqualTo(leftVar, rightVar)) {
399 makeLessThanOrEqualToConstant(result, 0);
400 }
401 break;
402
403 case BuiltinOperator.NumTruncatingDivideToSigned32:
404 if (isDefinitelyGreaterThanOrEqualToConstant(leftVar, 0)) {
405 // If we divide by a positive number, the result is closer to zero.
406 // If we divide by a negative number, the result is negative, and
407 // thus less than the original (non-negative) number.
408 // TODO(asgerf): The divisor is currently always positive, because
409 // type propagation checks that, but we could do better.
410 makeLessThanOrEqual(result, leftVar);
411 }
412 break;
413
414 case BuiltinOperator.NumShr:
415 if (isDefinitelyGreaterThanOrEqualToConstant(leftVar, 0)) {
416 makeLessThanOrEqual(result, leftVar);
417 }
sra1 2015/11/27 20:28:21 Also: x >> k <= MAX_UINT32 >> k Base64(De|En)c
asgerf 2015/11/30 13:46:03 Done.
418 break;
419
420 case BuiltinOperator.NumRemainder:
421 // TODO(asgerf): This check overlaps with checks performed in a type
422 // propagation transformation, and we can do it more precisely here.
423 // Should we do the rewrite here?
sra1 2015/11/27 20:28:21 We would want to do the check on InvokeMethod to s
asgerf 2015/11/30 13:46:03 My point was we could consider doing the rewriting
424 if (isDefinitelyGreaterThanOrEqualToConstant(leftVar, 0) &&
sra1 2015/11/27 20:28:21 We do this test a lot. How many steps does it take
asgerf 2015/11/30 13:46:03 The bounds checker is a bit wasteful like this, bu
asgerf 2015/12/01 16:19:35 I made unary checks a bit faster with a special ca
425 isDefinitelyGreaterThanOrEqualToConstant(rightVar, 1)) {
426 makeLessThanOrEqual(result, leftVar);
427 makeLessThan(result, rightVar);
428 }
429 break;
430
431 case BuiltinOperator.NumAnd:
432 // We use the faster UInt32 check instead of constraint based checks
433 // here, because the common case is that one operand is a constant.
434 if (isUInt32(left)) {
435 makeLessThanOrEqual(result, leftVar);
436 }
437 if (isUInt32(right)) {
438 makeLessThanOrEqual(result, rightVar);
439 }
440 break;
441
442 default:
443 }
444 }
445
446 void applyUnaryOperator(ApplyBuiltinOperator node) {
447 Primitive argument = node.arguments[0].definition;
448 if (!isInt(argument)) return;
449 if (node.operator == BuiltinOperator.NumNegate) {
450 valueOf[node] = getValue(argument).negated;
451 }
sra1 2015/11/27 20:28:21 ~x == MAX_UINT32 - x, if x is uint32. Not sure
asgerf 2015/11/30 13:46:03 Seems really unlikely to make a difference. Conne
452 }
453
454 int getIntConstant(Primitive prim) {
455 if (prim is Constant && prim.value.isInt) {
456 IntConstantValue constant = prim.value;
457 return constant.primitiveValue;
458 }
459 return null;
460 }
461
384 @override 462 @override
385 void visitGetLength(GetLength node) { 463 void visitGetLength(GetLength node) {
386 valueOf[node] = getLength(node.object.definition, currentEffectNumber); 464 valueOf[node] = getLength(node.object.definition, currentEffectNumber);
387 } 465 }
388 466
389 void analyzeLoopEntry(InvokeContinuation node) { 467 void analyzeLoopEntry(InvokeContinuation node) {
390 foundLoop = true; 468 foundLoop = true;
391 Continuation cont = node.continuation.definition; 469 Continuation cont = node.continuation.definition;
392 if (isStrongLoopPass) { 470 if (isStrongLoopPass) {
393 for (int i = 0; i < node.arguments.length; ++i) { 471 for (int i = 0; i < node.arguments.length; ++i) {
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 } 667 }
590 return node.body; 668 return node.body;
591 } 669 }
592 } 670 }
593 671
594 /// Lattice representing the known (weak) monotonicity of a loop variable. 672 /// Lattice representing the known (weak) monotonicity of a loop variable.
595 /// 673 ///
596 /// The lattice bottom is represented by `null` and represents the case where 674 /// The lattice bottom is represented by `null` and represents the case where
597 /// the loop variable never changes value during the loop. 675 /// the loop variable never changes value during the loop.
598 enum Monotonicity { NotMonotone, Increasing, Decreasing, } 676 enum Monotonicity { NotMonotone, Increasing, Decreasing, }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698