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

Side by Side Diff: src/compiler/machine-operator-reducer.cc

Issue 677483005: [turbofan] Implement the correct semantics for integer division/modulus. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fixes and tests Created 6 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « src/compiler/machine-operator-reducer.h ('k') | test/cctest/test-assembler-arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/machine-operator-reducer.h" 5 #include "src/compiler/machine-operator-reducer.h"
6 6
7 #include "src/base/bits.h" 7 #include "src/base/bits.h"
8 #include "src/base/division-by-constant.h" 8 #include "src/base/division-by-constant.h"
9 #include "src/codegen.h" 9 #include "src/codegen.h"
10 #include "src/compiler/generic-node-inl.h" 10 #include "src/compiler/generic-node-inl.h"
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 Node* MachineOperatorReducer::Word32Sar(Node* lhs, uint32_t rhs) { 51 Node* MachineOperatorReducer::Word32Sar(Node* lhs, uint32_t rhs) {
52 return graph()->NewNode(machine()->Word32Sar(), lhs, Uint32Constant(rhs)); 52 return graph()->NewNode(machine()->Word32Sar(), lhs, Uint32Constant(rhs));
53 } 53 }
54 54
55 55
56 Node* MachineOperatorReducer::Word32Shr(Node* lhs, uint32_t rhs) { 56 Node* MachineOperatorReducer::Word32Shr(Node* lhs, uint32_t rhs) {
57 return graph()->NewNode(machine()->Word32Shr(), lhs, Uint32Constant(rhs)); 57 return graph()->NewNode(machine()->Word32Shr(), lhs, Uint32Constant(rhs));
58 } 58 }
59 59
60 60
61 Node* MachineOperatorReducer::Word32Equal(Node* lhs, Node* rhs) {
62 return graph()->NewNode(machine()->Word32Equal(), lhs, rhs);
63 }
64
65
61 Node* MachineOperatorReducer::Int32Add(Node* lhs, Node* rhs) { 66 Node* MachineOperatorReducer::Int32Add(Node* lhs, Node* rhs) {
62 return graph()->NewNode(machine()->Int32Add(), lhs, rhs); 67 return graph()->NewNode(machine()->Int32Add(), lhs, rhs);
63 } 68 }
64 69
65 70
66 Node* MachineOperatorReducer::Int32Sub(Node* lhs, Node* rhs) { 71 Node* MachineOperatorReducer::Int32Sub(Node* lhs, Node* rhs) {
67 return graph()->NewNode(machine()->Int32Sub(), lhs, rhs); 72 return graph()->NewNode(machine()->Int32Sub(), lhs, rhs);
68 } 73 }
69 74
70 75
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 } 297 }
293 if (m.right().IsPowerOf2()) { // x * 2^n => x << n 298 if (m.right().IsPowerOf2()) { // x * 2^n => x << n
294 node->set_op(machine()->Word32Shl()); 299 node->set_op(machine()->Word32Shl());
295 node->ReplaceInput(1, Int32Constant(WhichPowerOf2(m.right().Value()))); 300 node->ReplaceInput(1, Int32Constant(WhichPowerOf2(m.right().Value())));
296 return Changed(node); 301 return Changed(node);
297 } 302 }
298 break; 303 break;
299 } 304 }
300 case IrOpcode::kInt32Div: 305 case IrOpcode::kInt32Div:
301 return ReduceInt32Div(node); 306 return ReduceInt32Div(node);
302 case IrOpcode::kUint32Div: { 307 case IrOpcode::kUint32Div:
303 Uint32BinopMatcher m(node); 308 return ReduceUint32Div(node);
304 if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x
305 // TODO(turbofan): if (m.left().Is(0))
306 // TODO(turbofan): if (m.right().Is(0))
307 // TODO(turbofan): if (m.LeftEqualsRight())
308 if (m.IsFoldable() && !m.right().Is(0)) { // K / K => K
309 return ReplaceInt32(m.left().Value() / m.right().Value());
310 }
311 if (m.right().IsPowerOf2()) { // x / 2^n => x >> n
312 node->set_op(machine()->Word32Shr());
313 node->ReplaceInput(1, Int32Constant(WhichPowerOf2(m.right().Value())));
314 return Changed(node);
315 }
316 break;
317 }
318 case IrOpcode::kInt32Mod: 309 case IrOpcode::kInt32Mod:
319 return ReduceInt32Mod(node); 310 return ReduceInt32Mod(node);
320 case IrOpcode::kUint32Mod: { 311 case IrOpcode::kUint32Mod:
321 Uint32BinopMatcher m(node); 312 return ReduceUint32Mod(node);
322 if (m.right().Is(1)) return ReplaceInt32(0); // x % 1 => 0
323 // TODO(turbofan): if (m.left().Is(0))
324 // TODO(turbofan): if (m.right().Is(0))
325 // TODO(turbofan): if (m.LeftEqualsRight())
326 if (m.IsFoldable() && !m.right().Is(0)) { // K % K => K
327 return ReplaceInt32(m.left().Value() % m.right().Value());
328 }
329 if (m.right().IsPowerOf2()) { // x % 2^n => x & 2^n-1
330 node->set_op(machine()->Word32And());
331 node->ReplaceInput(1, Int32Constant(m.right().Value() - 1));
332 return Changed(node);
333 }
334 break;
335 }
336 case IrOpcode::kInt32LessThan: { 313 case IrOpcode::kInt32LessThan: {
337 Int32BinopMatcher m(node); 314 Int32BinopMatcher m(node);
338 if (m.IsFoldable()) { // K < K => K 315 if (m.IsFoldable()) { // K < K => K
339 return ReplaceBool(m.left().Value() < m.right().Value()); 316 return ReplaceBool(m.left().Value() < m.right().Value());
340 } 317 }
341 if (m.left().IsInt32Sub() && m.right().Is(0)) { // x - y < 0 => x < y 318 if (m.left().IsInt32Sub() && m.right().Is(0)) { // x - y < 0 => x < y
342 Int32BinopMatcher msub(m.left().node()); 319 Int32BinopMatcher msub(m.left().node());
343 node->ReplaceInput(0, msub.left().node()); 320 node->ReplaceInput(0, msub.left().node());
344 node->ReplaceInput(1, msub.right().node()); 321 node->ReplaceInput(1, msub.right().node());
345 return Changed(node); 322 return Changed(node);
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 } 524 }
548 default: 525 default:
549 break; 526 break;
550 } 527 }
551 return NoChange(); 528 return NoChange();
552 } 529 }
553 530
554 531
555 Reduction MachineOperatorReducer::ReduceInt32Div(Node* node) { 532 Reduction MachineOperatorReducer::ReduceInt32Div(Node* node) {
556 Int32BinopMatcher m(node); 533 Int32BinopMatcher m(node);
534 if (m.left().Is(0)) return Replace(m.left().node()); // 0 / x => 0
557 if (m.right().Is(0)) return Replace(m.right().node()); // x / 0 => 0 535 if (m.right().Is(0)) return Replace(m.right().node()); // x / 0 => 0
558 if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x 536 if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x
559 // TODO(turbofan): if (m.left().Is(0)) 537 if (m.IsFoldable()) { // K / K => K
560 // TODO(turbofan): if (m.LeftEqualsRight()) 538 return ReplaceInt32(
561 if (m.IsFoldable() && !m.right().Is(0)) { // K / K => K 539 base::bits::SignedDiv32(m.left().Value(), m.right().Value()));
562 if (m.right().Is(-1)) return ReplaceInt32(-m.left().Value()); 540 }
563 return ReplaceInt32(m.left().Value() / m.right().Value()); 541 if (m.LeftEqualsRight()) { // x / x => x != 0
542 Node* const zero = Int32Constant(0);
543 return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero));
564 } 544 }
565 if (m.right().Is(-1)) { // x / -1 => 0 - x 545 if (m.right().Is(-1)) { // x / -1 => 0 - x
566 node->set_op(machine()->Int32Sub()); 546 node->set_op(machine()->Int32Sub());
567 node->ReplaceInput(0, Int32Constant(0)); 547 node->ReplaceInput(0, Int32Constant(0));
568 node->ReplaceInput(1, m.left().node()); 548 node->ReplaceInput(1, m.left().node());
569 return Changed(node); 549 return Changed(node);
570 } 550 }
571 if (m.right().HasValue()) { 551 if (m.right().HasValue()) {
572 int32_t const divisor = m.right().Value(); 552 int32_t const divisor = m.right().Value();
573 Node* const dividend = m.left().node(); 553 Node* const dividend = m.left().node();
(...skipping 14 matching lines...) Expand all
588 node->ReplaceInput(0, Int32Constant(0)); 568 node->ReplaceInput(0, Int32Constant(0));
589 node->ReplaceInput(1, quotient); 569 node->ReplaceInput(1, quotient);
590 return Changed(node); 570 return Changed(node);
591 } 571 }
592 return Replace(quotient); 572 return Replace(quotient);
593 } 573 }
594 return NoChange(); 574 return NoChange();
595 } 575 }
596 576
597 577
578 Reduction MachineOperatorReducer::ReduceUint32Div(Node* node) {
579 Uint32BinopMatcher m(node);
580 if (m.left().Is(0)) return Replace(m.left().node()); // 0 / x => 0
581 if (m.right().Is(0)) return Replace(m.right().node()); // x / 0 => 0
582 if (m.right().Is(1)) return Replace(m.left().node()); // x / 1 => x
583 if (m.IsFoldable()) { // K / K => K
584 return ReplaceUint32(
585 base::bits::UnsignedDiv32(m.left().Value(), m.right().Value()));
586 }
587 if (m.LeftEqualsRight()) { // x / x => x != 0
588 Node* const zero = Int32Constant(0);
589 return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero));
590 }
591 if (m.right().IsPowerOf2()) { // x / 2^n => x >> n
592 node->set_op(machine()->Word32Shr());
593 node->ReplaceInput(1, Uint32Constant(WhichPowerOf2(m.right().Value())));
594 return Changed(node);
595 }
596 return NoChange();
597 }
598
599
598 Reduction MachineOperatorReducer::ReduceInt32Mod(Node* node) { 600 Reduction MachineOperatorReducer::ReduceInt32Mod(Node* node) {
599 Int32BinopMatcher m(node); 601 Int32BinopMatcher m(node);
600 if (m.right().Is(1)) return ReplaceInt32(0); // x % 1 => 0 602 if (m.left().Is(0)) return Replace(m.left().node()); // 0 % x => 0
601 if (m.right().Is(-1)) return ReplaceInt32(0); // x % -1 => 0 603 if (m.right().Is(0)) return Replace(m.right().node()); // x % 0 => 0
602 // TODO(turbofan): if (m.left().Is(0)) 604 if (m.right().Is(1)) return ReplaceInt32(0); // x % 1 => 0
603 // TODO(turbofan): if (m.right().Is(0)) 605 if (m.right().Is(-1)) return ReplaceInt32(0); // x % -1 => 0
604 // TODO(turbofan): if (m.LeftEqualsRight()) 606 if (m.LeftEqualsRight()) return ReplaceInt32(0); // x % x => 0
605 if (m.IsFoldable() && !m.right().Is(0)) { // K % K => K 607 if (m.IsFoldable()) { // K % K => K
606 return ReplaceInt32(m.left().Value() % m.right().Value()); 608 return ReplaceInt32(
609 base::bits::SignedMod32(m.left().Value(), m.right().Value()));
607 } 610 }
608 if (m.right().HasValue()) { 611 if (m.right().HasValue()) {
609 Node* const dividend = m.left().node(); 612 Node* const dividend = m.left().node();
610 int32_t const divisor = Abs(m.right().Value()); 613 int32_t const divisor = Abs(m.right().Value());
611 if (base::bits::IsPowerOfTwo32(divisor)) { 614 if (base::bits::IsPowerOfTwo32(divisor)) {
612 uint32_t const mask = divisor - 1; 615 uint32_t const mask = divisor - 1;
613 Node* const zero = Int32Constant(0); 616 Node* const zero = Int32Constant(0);
614 617
615 Node* check = 618 Node* check =
616 graph()->NewNode(machine()->Int32LessThan(), dividend, zero); 619 graph()->NewNode(machine()->Int32LessThan(), dividend, zero);
(...skipping 15 matching lines...) Expand all
632 node->set_op(machine()->Int32Sub()); 635 node->set_op(machine()->Int32Sub());
633 DCHECK_EQ(dividend, node->InputAt(0)); 636 DCHECK_EQ(dividend, node->InputAt(0));
634 node->ReplaceInput(1, Int32Mul(quotient, Int32Constant(divisor))); 637 node->ReplaceInput(1, Int32Mul(quotient, Int32Constant(divisor)));
635 return Changed(node); 638 return Changed(node);
636 } 639 }
637 } 640 }
638 return NoChange(); 641 return NoChange();
639 } 642 }
640 643
641 644
645 Reduction MachineOperatorReducer::ReduceUint32Mod(Node* node) {
646 Uint32BinopMatcher m(node);
647 if (m.left().Is(0)) return Replace(m.left().node()); // 0 % x => 0
648 if (m.right().Is(0)) return Replace(m.right().node()); // x % 0 => 0
649 if (m.right().Is(1)) return ReplaceUint32(0); // x % 1 => 0
650 if (m.LeftEqualsRight()) return ReplaceInt32(0); // x % x => 0
651 if (m.IsFoldable()) { // K % K => K
652 return ReplaceUint32(
653 base::bits::UnsignedMod32(m.left().Value(), m.right().Value()));
654 }
655 if (m.right().IsPowerOf2()) { // x % 2^n => x & 2^n-1
656 node->set_op(machine()->Word32And());
657 node->ReplaceInput(1, Uint32Constant(m.right().Value() - 1));
658 return Changed(node);
659 }
660 return NoChange();
661 }
662
663
642 Reduction MachineOperatorReducer::ReduceProjection(size_t index, Node* node) { 664 Reduction MachineOperatorReducer::ReduceProjection(size_t index, Node* node) {
643 switch (node->opcode()) { 665 switch (node->opcode()) {
644 case IrOpcode::kInt32AddWithOverflow: { 666 case IrOpcode::kInt32AddWithOverflow: {
645 DCHECK(index == 0 || index == 1); 667 DCHECK(index == 0 || index == 1);
646 Int32BinopMatcher m(node); 668 Int32BinopMatcher m(node);
647 if (m.IsFoldable()) { 669 if (m.IsFoldable()) {
648 int32_t val; 670 int32_t val;
649 bool ovf = base::bits::SignedAddOverflow32(m.left().Value(), 671 bool ovf = base::bits::SignedAddOverflow32(m.left().Value(),
650 m.right().Value(), &val); 672 m.right().Value(), &val);
651 return ReplaceInt32((index == 0) ? val : ovf); 673 return ReplaceInt32((index == 0) ? val : ovf);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
684 MachineOperatorBuilder* MachineOperatorReducer::machine() const { 706 MachineOperatorBuilder* MachineOperatorReducer::machine() const {
685 return jsgraph()->machine(); 707 return jsgraph()->machine();
686 } 708 }
687 709
688 710
689 Graph* MachineOperatorReducer::graph() const { return jsgraph()->graph(); } 711 Graph* MachineOperatorReducer::graph() const { return jsgraph()->graph(); }
690 712
691 } // namespace compiler 713 } // namespace compiler
692 } // namespace internal 714 } // namespace internal
693 } // namespace v8 715 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/machine-operator-reducer.h ('k') | test/cctest/test-assembler-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698