OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 tree_ir.optimization.logical_rewriter; | 5 library tree_ir.optimization.logical_rewriter; |
6 | 6 |
7 import '../tree_ir_nodes.dart'; | 7 import '../tree_ir_nodes.dart'; |
8 import 'optimization.dart' show Pass; | 8 import 'optimization.dart' show Pass; |
9 import '../../constants/values.dart' as values; | 9 import '../../constants/values.dart' as values; |
10 | 10 |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 node.condition = makeCondition(node.condition, true); | 299 node.condition = makeCondition(node.condition, true); |
300 | 300 |
301 // !x ? y : z ==> x ? z : y | 301 // !x ? y : z ==> x ? z : y |
302 if (node.condition is Not) { | 302 if (node.condition is Not) { |
303 node.condition = (node.condition as Not).operand; | 303 node.condition = (node.condition as Not).operand; |
304 Expression tmp = node.thenExpression; | 304 Expression tmp = node.thenExpression; |
305 node.thenExpression = node.elseExpression; | 305 node.thenExpression = node.elseExpression; |
306 node.elseExpression = tmp; | 306 node.elseExpression = tmp; |
307 } | 307 } |
308 | 308 |
| 309 // x ? y : x ==> x && y |
| 310 if (isSameVariable(node.condition, node.elseExpression)) { |
| 311 destroyVariableUse(node.elseExpression); |
| 312 return new LogicalOperator.and(node.condition, node.thenExpression); |
| 313 } |
| 314 // x ? x : y ==> x || y |
| 315 if (isSameVariable(node.condition, node.thenExpression)) { |
| 316 destroyVariableUse(node.thenExpression); |
| 317 return new LogicalOperator.or(node.condition, node.elseExpression); |
| 318 } |
| 319 |
309 return node; | 320 return node; |
310 } | 321 } |
311 | 322 |
312 Expression visitLogicalOperator(LogicalOperator node) { | 323 Expression visitLogicalOperator(LogicalOperator node) { |
313 node.left = visitExpression(node.left); | 324 node.left = visitExpression(node.left); |
314 node.right = visitExpression(node.right); | 325 node.right = visitExpression(node.right); |
315 return node; | 326 return node; |
316 } | 327 } |
317 | 328 |
318 /// True if the given expression is known to evaluate to a boolean. | 329 /// True if the given expression is known to evaluate to a boolean. |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
461 Expression tmp = e.thenExpression; | 472 Expression tmp = e.thenExpression; |
462 e.thenExpression = e.elseExpression; | 473 e.thenExpression = e.elseExpression; |
463 e.elseExpression = tmp; | 474 e.elseExpression = tmp; |
464 } | 475 } |
465 // x ? !y : !z ==> !(x ? y : z) (only if lifting nots) | 476 // x ? !y : !z ==> !(x ? y : z) (only if lifting nots) |
466 if (e.thenExpression is Not && e.elseExpression is Not && liftNots) { | 477 if (e.thenExpression is Not && e.elseExpression is Not && liftNots) { |
467 e.thenExpression = (e.thenExpression as Not).operand; | 478 e.thenExpression = (e.thenExpression as Not).operand; |
468 e.elseExpression = (e.elseExpression as Not).operand; | 479 e.elseExpression = (e.elseExpression as Not).operand; |
469 return new Not(e); | 480 return new Not(e); |
470 } | 481 } |
| 482 |
| 483 // x ? y : x ==> x && y |
| 484 if (isSameVariable(e.condition, e.elseExpression)) { |
| 485 destroyVariableUse(e.elseExpression); |
| 486 return new LogicalOperator.and(e.condition, e.thenExpression); |
| 487 } |
| 488 // x ? x : y ==> x || y |
| 489 if (isSameVariable(e.condition, e.thenExpression)) { |
| 490 destroyVariableUse(e.thenExpression); |
| 491 return new LogicalOperator.or(e.condition, e.elseExpression); |
| 492 } |
| 493 |
471 return e; | 494 return e; |
472 } | 495 } |
473 if (e is Constant && e.value.isBool) { | 496 if (e is Constant && e.value.isBool) { |
474 // !true ==> false | 497 // !true ==> false |
475 if (!polarity) { | 498 if (!polarity) { |
476 values.BoolConstantValue value = e.value; | 499 values.BoolConstantValue value = e.value; |
477 return new Constant.bool(value.negate()); | 500 return new Constant.bool(value.negate()); |
478 } | 501 } |
479 return e; | 502 return e; |
480 } | 503 } |
(...skipping 21 matching lines...) Expand all Loading... |
502 } | 525 } |
503 } | 526 } |
504 | 527 |
505 Expression makeOr(Expression e1, Expression e2, {bool liftNots: true}) { | 528 Expression makeOr(Expression e1, Expression e2, {bool liftNots: true}) { |
506 if (e1 is Not && e2 is Not && liftNots) { | 529 if (e1 is Not && e2 is Not && liftNots) { |
507 return new Not(new LogicalOperator.and(e1.operand, e2.operand)); | 530 return new Not(new LogicalOperator.and(e1.operand, e2.operand)); |
508 } else { | 531 } else { |
509 return new LogicalOperator.or(e1, e2); | 532 return new LogicalOperator.or(e1, e2); |
510 } | 533 } |
511 } | 534 } |
| 535 |
| 536 /// True if [e2] is known to return the same value as [e1] |
| 537 /// (with no additional side effects) if evaluated immediately after [e1]. |
| 538 /// |
| 539 /// Concretely, this is true if [e1] and [e2] are uses of the same variable, |
| 540 /// or if [e2] is a use of a variable assigned by [e1]. |
| 541 bool isSameVariable(Expression e1, Expression e2) { |
| 542 if (e1 is VariableUse) { |
| 543 return e2 is VariableUse && e1.variable == e2.variable; |
| 544 } else if (e1 is Assign) { |
| 545 return e2 is VariableUse && e1.variable == e2.variable; |
| 546 } |
| 547 return false; |
| 548 } |
| 549 |
| 550 void destroyVariableUse(VariableUse node) { |
| 551 --node.variable.readCount; |
| 552 } |
512 } | 553 } |
513 | 554 |
OLD | NEW |