| OLD | NEW |
| 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 "test/cctest/cctest.h" | 5 #include "test/cctest/cctest.h" |
| 6 | 6 |
| 7 #include "src/base/utils/random-number-generator.h" | 7 #include "src/base/utils/random-number-generator.h" |
| 8 #include "src/codegen.h" | 8 #include "src/codegen.h" |
| 9 #include "src/compiler/graph-inl.h" | 9 #include "src/compiler/graph-inl.h" |
| 10 #include "src/compiler/js-graph.h" | 10 #include "src/compiler/js-graph.h" |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 // yields the {expect} value. | 93 // yields the {expect} value. |
| 94 template <typename T> | 94 template <typename T> |
| 95 void CheckFoldBinop(volatile T expect, volatile T a, volatile T b) { | 95 void CheckFoldBinop(volatile T expect, volatile T a, volatile T b) { |
| 96 CheckFoldBinop<T>(expect, Constant<T>(a), Constant<T>(b)); | 96 CheckFoldBinop<T>(expect, Constant<T>(a), Constant<T>(b)); |
| 97 } | 97 } |
| 98 | 98 |
| 99 // Check that the reduction of this binop applied to {a} and {b} yields | 99 // Check that the reduction of this binop applied to {a} and {b} yields |
| 100 // the {expect} value. | 100 // the {expect} value. |
| 101 template <typename T> | 101 template <typename T> |
| 102 void CheckFoldBinop(volatile T expect, Node* a, Node* b) { | 102 void CheckFoldBinop(volatile T expect, Node* a, Node* b) { |
| 103 CHECK_NE(NULL, binop); | 103 CHECK(binop); |
| 104 Node* n = CreateBinopNode(a, b); | 104 Node* n = CreateBinopNode(a, b); |
| 105 MachineOperatorReducer reducer(&jsgraph); | 105 MachineOperatorReducer reducer(&jsgraph); |
| 106 Reduction reduction = reducer.Reduce(n); | 106 Reduction reduction = reducer.Reduce(n); |
| 107 CHECK(reduction.Changed()); | 107 CHECK(reduction.Changed()); |
| 108 CHECK_NE(n, reduction.replacement()); | 108 CHECK_NE(n, reduction.replacement()); |
| 109 CHECK_EQ(expect, ValueOf<T>(reduction.replacement()->op())); | 109 CHECK_EQ(expect, ValueOf<T>(reduction.replacement()->op())); |
| 110 } | 110 } |
| 111 | 111 |
| 112 // Check that the reduction of this binop applied to {a} and {b} yields | 112 // Check that the reduction of this binop applied to {a} and {b} yields |
| 113 // the {expect} node. | 113 // the {expect} node. |
| 114 void CheckBinop(Node* expect, Node* a, Node* b) { | 114 void CheckBinop(Node* expect, Node* a, Node* b) { |
| 115 CHECK_NE(NULL, binop); | 115 CHECK(binop); |
| 116 Node* n = CreateBinopNode(a, b); | 116 Node* n = CreateBinopNode(a, b); |
| 117 MachineOperatorReducer reducer(&jsgraph); | 117 MachineOperatorReducer reducer(&jsgraph); |
| 118 Reduction reduction = reducer.Reduce(n); | 118 Reduction reduction = reducer.Reduce(n); |
| 119 CHECK(reduction.Changed()); | 119 CHECK(reduction.Changed()); |
| 120 CHECK_EQ(expect, reduction.replacement()); | 120 CHECK_EQ(expect, reduction.replacement()); |
| 121 } | 121 } |
| 122 | 122 |
| 123 // Check that the reduction of this binop applied to {left} and {right} yields | 123 // Check that the reduction of this binop applied to {left} and {right} yields |
| 124 // this binop applied to {left_expect} and {right_expect}. | 124 // this binop applied to {left_expect} and {right_expect}. |
| 125 void CheckFoldBinop(Node* left_expect, Node* right_expect, Node* left, | 125 void CheckFoldBinop(Node* left_expect, Node* right_expect, Node* left, |
| 126 Node* right) { | 126 Node* right) { |
| 127 CHECK_NE(NULL, binop); | 127 CHECK(binop); |
| 128 Node* n = CreateBinopNode(left, right); | 128 Node* n = CreateBinopNode(left, right); |
| 129 MachineOperatorReducer reducer(&jsgraph); | 129 MachineOperatorReducer reducer(&jsgraph); |
| 130 Reduction reduction = reducer.Reduce(n); | 130 Reduction reduction = reducer.Reduce(n); |
| 131 CHECK(reduction.Changed()); | 131 CHECK(reduction.Changed()); |
| 132 CHECK_EQ(binop, reduction.replacement()->op()); | 132 CHECK_EQ(binop, reduction.replacement()->op()); |
| 133 CHECK_EQ(left_expect, reduction.replacement()->InputAt(0)); | 133 CHECK_EQ(left_expect, reduction.replacement()->InputAt(0)); |
| 134 CHECK_EQ(right_expect, reduction.replacement()->InputAt(1)); | 134 CHECK_EQ(right_expect, reduction.replacement()->InputAt(1)); |
| 135 } | 135 } |
| 136 | 136 |
| 137 // Check that the reduction of this binop applied to {left} and {right} yields | 137 // Check that the reduction of this binop applied to {left} and {right} yields |
| 138 // the {op_expect} applied to {left_expect} and {right_expect}. | 138 // the {op_expect} applied to {left_expect} and {right_expect}. |
| 139 template <typename T> | 139 template <typename T> |
| 140 void CheckFoldBinop(volatile T left_expect, const Operator* op_expect, | 140 void CheckFoldBinop(volatile T left_expect, const Operator* op_expect, |
| 141 Node* right_expect, Node* left, Node* right) { | 141 Node* right_expect, Node* left, Node* right) { |
| 142 CHECK_NE(NULL, binop); | 142 CHECK(binop); |
| 143 Node* n = CreateBinopNode(left, right); | 143 Node* n = CreateBinopNode(left, right); |
| 144 MachineOperatorReducer reducer(&jsgraph); | 144 MachineOperatorReducer reducer(&jsgraph); |
| 145 Reduction r = reducer.Reduce(n); | 145 Reduction r = reducer.Reduce(n); |
| 146 CHECK(r.Changed()); | 146 CHECK(r.Changed()); |
| 147 CHECK_EQ(op_expect->opcode(), r.replacement()->op()->opcode()); | 147 CHECK_EQ(op_expect->opcode(), r.replacement()->op()->opcode()); |
| 148 CHECK_EQ(left_expect, ValueOf<T>(r.replacement()->InputAt(0)->op())); | 148 CHECK_EQ(left_expect, ValueOf<T>(r.replacement()->InputAt(0)->op())); |
| 149 CHECK_EQ(right_expect, r.replacement()->InputAt(1)); | 149 CHECK_EQ(right_expect, r.replacement()->InputAt(1)); |
| 150 } | 150 } |
| 151 | 151 |
| 152 // Check that the reduction of this binop applied to {left} and {right} yields | 152 // Check that the reduction of this binop applied to {left} and {right} yields |
| 153 // the {op_expect} applied to {left_expect} and {right_expect}. | 153 // the {op_expect} applied to {left_expect} and {right_expect}. |
| 154 template <typename T> | 154 template <typename T> |
| 155 void CheckFoldBinop(Node* left_expect, const Operator* op_expect, | 155 void CheckFoldBinop(Node* left_expect, const Operator* op_expect, |
| 156 volatile T right_expect, Node* left, Node* right) { | 156 volatile T right_expect, Node* left, Node* right) { |
| 157 CHECK_NE(NULL, binop); | 157 CHECK(binop); |
| 158 Node* n = CreateBinopNode(left, right); | 158 Node* n = CreateBinopNode(left, right); |
| 159 MachineOperatorReducer reducer(&jsgraph); | 159 MachineOperatorReducer reducer(&jsgraph); |
| 160 Reduction r = reducer.Reduce(n); | 160 Reduction r = reducer.Reduce(n); |
| 161 CHECK(r.Changed()); | 161 CHECK(r.Changed()); |
| 162 CHECK_EQ(op_expect->opcode(), r.replacement()->op()->opcode()); | 162 CHECK_EQ(op_expect->opcode(), r.replacement()->op()->opcode()); |
| 163 CHECK_EQ(OperatorProperties::GetTotalInputCount(op_expect), | 163 CHECK_EQ(OperatorProperties::GetTotalInputCount(op_expect), |
| 164 r.replacement()->InputCount()); | 164 r.replacement()->InputCount()); |
| 165 CHECK_EQ(left_expect, r.replacement()->InputAt(0)); | 165 CHECK_EQ(left_expect, r.replacement()->InputAt(0)); |
| 166 CHECK_EQ(right_expect, ValueOf<T>(r.replacement()->InputAt(1)->op())); | 166 CHECK_EQ(right_expect, ValueOf<T>(r.replacement()->InputAt(1)->op())); |
| 167 } | 167 } |
| (...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 716 Node* store = R.graph.NewNode( | 716 Node* store = R.graph.NewNode( |
| 717 R.machine.Store(StoreRepresentation(kMachInt32, kNoWriteBarrier)), base, | 717 R.machine.Store(StoreRepresentation(kMachInt32, kNoWriteBarrier)), base, |
| 718 index, load); | 718 index, load); |
| 719 MachineOperatorReducer reducer(&R.jsgraph); | 719 MachineOperatorReducer reducer(&R.jsgraph); |
| 720 Reduction reduction = reducer.Reduce(store); | 720 Reduction reduction = reducer.Reduce(store); |
| 721 CHECK(!reduction.Changed()); // stores should not be reduced. | 721 CHECK(!reduction.Changed()); // stores should not be reduced. |
| 722 } | 722 } |
| 723 } | 723 } |
| 724 | 724 |
| 725 | 725 |
| 726 static void CheckNans(ReducerTester* R) { | |
| 727 Node* x = R->Parameter(); | |
| 728 std::vector<double> nans = ValueHelper::nan_vector(); | |
| 729 for (std::vector<double>::const_iterator pl = nans.begin(); pl != nans.end(); | |
| 730 ++pl) { | |
| 731 for (std::vector<double>::const_iterator pr = nans.begin(); | |
| 732 pr != nans.end(); ++pr) { | |
| 733 Node* nan1 = R->Constant<double>(*pl); | |
| 734 Node* nan2 = R->Constant<double>(*pr); | |
| 735 R->CheckBinop(nan1, x, nan1); // x op NaN => NaN | |
| 736 R->CheckBinop(nan1, nan1, x); // NaN op x => NaN | |
| 737 R->CheckBinop(nan1, nan2, nan1); // NaN op NaN => NaN | |
| 738 } | |
| 739 } | |
| 740 } | |
| 741 | |
| 742 | |
| 743 TEST(ReduceFloat64Add) { | |
| 744 ReducerTester R; | |
| 745 R.binop = R.machine.Float64Add(); | |
| 746 | |
| 747 FOR_FLOAT64_INPUTS(pl) { | |
| 748 FOR_FLOAT64_INPUTS(pr) { | |
| 749 double x = *pl, y = *pr; | |
| 750 R.CheckFoldBinop<double>(x + y, x, y); | |
| 751 } | |
| 752 } | |
| 753 | |
| 754 FOR_FLOAT64_INPUTS(i) { | |
| 755 Double tmp(*i); | |
| 756 if (!tmp.IsSpecial() || tmp.IsInfinite()) { | |
| 757 // Don't check NaNs as they are reduced more. | |
| 758 R.CheckPutConstantOnRight(*i); | |
| 759 } | |
| 760 } | |
| 761 | |
| 762 CheckNans(&R); | |
| 763 } | |
| 764 | |
| 765 | |
| 766 TEST(ReduceFloat64Sub) { | |
| 767 ReducerTester R; | |
| 768 R.binop = R.machine.Float64Sub(); | |
| 769 | |
| 770 FOR_FLOAT64_INPUTS(pl) { | |
| 771 FOR_FLOAT64_INPUTS(pr) { | |
| 772 double x = *pl, y = *pr; | |
| 773 R.CheckFoldBinop<double>(x - y, x, y); | |
| 774 } | |
| 775 } | |
| 776 | |
| 777 Node* zero = R.Constant<double>(0.0); | |
| 778 Node* x = R.Parameter(); | |
| 779 | |
| 780 R.CheckBinop(x, x, zero); // x - 0.0 => x | |
| 781 | |
| 782 CheckNans(&R); | |
| 783 } | |
| 784 | |
| 785 | |
| 786 TEST(ReduceFloat64Mul) { | |
| 787 ReducerTester R; | |
| 788 R.binop = R.machine.Float64Mul(); | |
| 789 | |
| 790 FOR_FLOAT64_INPUTS(pl) { | |
| 791 FOR_FLOAT64_INPUTS(pr) { | |
| 792 double x = *pl, y = *pr; | |
| 793 R.CheckFoldBinop<double>(x * y, x, y); | |
| 794 } | |
| 795 } | |
| 796 | |
| 797 double inf = V8_INFINITY; | |
| 798 R.CheckPutConstantOnRight(-inf); | |
| 799 R.CheckPutConstantOnRight(-0.1); | |
| 800 R.CheckPutConstantOnRight(0.1); | |
| 801 R.CheckPutConstantOnRight(inf); | |
| 802 | |
| 803 Node* x = R.Parameter(); | |
| 804 Node* one = R.Constant<double>(1.0); | |
| 805 | |
| 806 R.CheckBinop(x, x, one); // x * 1.0 => x | |
| 807 R.CheckBinop(x, one, x); // 1.0 * x => x | |
| 808 | |
| 809 CheckNans(&R); | |
| 810 } | |
| 811 | |
| 812 | |
| 813 TEST(ReduceFloat64Div) { | |
| 814 ReducerTester R; | |
| 815 R.binop = R.machine.Float64Div(); | |
| 816 | |
| 817 FOR_FLOAT64_INPUTS(pl) { | |
| 818 FOR_FLOAT64_INPUTS(pr) { | |
| 819 double x = *pl, y = *pr; | |
| 820 R.CheckFoldBinop<double>(x / y, x, y); | |
| 821 } | |
| 822 } | |
| 823 | |
| 824 Node* x = R.Parameter(); | |
| 825 Node* one = R.Constant<double>(1.0); | |
| 826 | |
| 827 R.CheckBinop(x, x, one); // x / 1.0 => x | |
| 828 | |
| 829 CheckNans(&R); | |
| 830 } | |
| 831 | |
| 832 | |
| 833 TEST(ReduceFloat64Mod) { | |
| 834 ReducerTester R; | |
| 835 R.binop = R.machine.Float64Mod(); | |
| 836 | |
| 837 FOR_FLOAT64_INPUTS(pl) { | |
| 838 FOR_FLOAT64_INPUTS(pr) { | |
| 839 double x = *pl, y = *pr; | |
| 840 R.CheckFoldBinop<double>(modulo(x, y), x, y); | |
| 841 } | |
| 842 } | |
| 843 | |
| 844 Node* x = R.Parameter(); | |
| 845 Node* zero = R.Constant<double>(0.0); | |
| 846 | |
| 847 R.CheckFoldBinop<double>(std::numeric_limits<double>::quiet_NaN(), x, zero); | |
| 848 | |
| 849 CheckNans(&R); | |
| 850 } | |
| 851 | |
| 852 | |
| 853 // TODO(titzer): test MachineOperatorReducer for Word64And | 726 // TODO(titzer): test MachineOperatorReducer for Word64And |
| 854 // TODO(titzer): test MachineOperatorReducer for Word64Or | 727 // TODO(titzer): test MachineOperatorReducer for Word64Or |
| 855 // TODO(titzer): test MachineOperatorReducer for Word64Xor | 728 // TODO(titzer): test MachineOperatorReducer for Word64Xor |
| 856 // TODO(titzer): test MachineOperatorReducer for Word64Shl | 729 // TODO(titzer): test MachineOperatorReducer for Word64Shl |
| 857 // TODO(titzer): test MachineOperatorReducer for Word64Shr | 730 // TODO(titzer): test MachineOperatorReducer for Word64Shr |
| 858 // TODO(titzer): test MachineOperatorReducer for Word64Sar | 731 // TODO(titzer): test MachineOperatorReducer for Word64Sar |
| 859 // TODO(titzer): test MachineOperatorReducer for Word64Equal | 732 // TODO(titzer): test MachineOperatorReducer for Word64Equal |
| 860 // TODO(titzer): test MachineOperatorReducer for Word64Not | 733 // TODO(titzer): test MachineOperatorReducer for Word64Not |
| 861 // TODO(titzer): test MachineOperatorReducer for Int64Add | 734 // TODO(titzer): test MachineOperatorReducer for Int64Add |
| 862 // TODO(titzer): test MachineOperatorReducer for Int64Sub | 735 // TODO(titzer): test MachineOperatorReducer for Int64Sub |
| 863 // TODO(titzer): test MachineOperatorReducer for Int64Mul | 736 // TODO(titzer): test MachineOperatorReducer for Int64Mul |
| 864 // TODO(titzer): test MachineOperatorReducer for Int64UMul | 737 // TODO(titzer): test MachineOperatorReducer for Int64UMul |
| 865 // TODO(titzer): test MachineOperatorReducer for Int64Div | 738 // TODO(titzer): test MachineOperatorReducer for Int64Div |
| 866 // TODO(titzer): test MachineOperatorReducer for Uint64Div | 739 // TODO(titzer): test MachineOperatorReducer for Uint64Div |
| 867 // TODO(titzer): test MachineOperatorReducer for Int64Mod | 740 // TODO(titzer): test MachineOperatorReducer for Int64Mod |
| 868 // TODO(titzer): test MachineOperatorReducer for Uint64Mod | 741 // TODO(titzer): test MachineOperatorReducer for Uint64Mod |
| 869 // TODO(titzer): test MachineOperatorReducer for Int64Neg | 742 // TODO(titzer): test MachineOperatorReducer for Int64Neg |
| 870 // TODO(titzer): test MachineOperatorReducer for ChangeInt32ToFloat64 | 743 // TODO(titzer): test MachineOperatorReducer for ChangeInt32ToFloat64 |
| 871 // TODO(titzer): test MachineOperatorReducer for ChangeFloat64ToInt32 | 744 // TODO(titzer): test MachineOperatorReducer for ChangeFloat64ToInt32 |
| 872 // TODO(titzer): test MachineOperatorReducer for Float64Compare | 745 // TODO(titzer): test MachineOperatorReducer for Float64Compare |
| 746 // TODO(titzer): test MachineOperatorReducer for Float64Add |
| 747 // TODO(titzer): test MachineOperatorReducer for Float64Sub |
| 748 // TODO(titzer): test MachineOperatorReducer for Float64Mul |
| 749 // TODO(titzer): test MachineOperatorReducer for Float64Div |
| 750 // TODO(titzer): test MachineOperatorReducer for Float64Mod |
| OLD | NEW |