| 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 "src/code-stubs.h" | 5 #include "src/code-stubs.h" |
| 6 #include "src/compiler/change-lowering.h" | 6 #include "src/compiler/change-lowering.h" |
| 7 #include "src/compiler/js-graph.h" | 7 #include "src/compiler/js-graph.h" |
| 8 #include "src/compiler/linkage.h" | 8 #include "src/compiler/linkage.h" |
| 9 #include "src/compiler/node-properties.h" | 9 #include "src/compiler/node-properties.h" |
| 10 #include "src/compiler/simplified-operator.h" | 10 #include "src/compiler/simplified-operator.h" |
| 11 #include "test/unittests/compiler/compiler-test-utils.h" | 11 #include "test/unittests/compiler/compiler-test-utils.h" |
| 12 #include "test/unittests/compiler/graph-unittest.h" | 12 #include "test/unittests/compiler/graph-unittest.h" |
| 13 #include "test/unittests/compiler/node-test-utils.h" | 13 #include "test/unittests/compiler/node-test-utils.h" |
| 14 #include "testing/gmock-support.h" | 14 #include "testing/gmock-support.h" |
| 15 | 15 |
| 16 using testing::_; | 16 using testing::_; |
| 17 using testing::AllOf; | 17 using testing::AllOf; |
| 18 using testing::BitEq; | 18 using testing::BitEq; |
| 19 using testing::Capture; | 19 using testing::Capture; |
| 20 using testing::CaptureEq; | 20 using testing::CaptureEq; |
| 21 | 21 |
| 22 namespace v8 { | 22 namespace v8 { |
| 23 namespace internal { | 23 namespace internal { |
| 24 namespace compiler { | 24 namespace compiler { |
| 25 | 25 |
| 26 class ChangeLoweringTest : public GraphTest { | 26 class ChangeLoweringTest : public TypedGraphTest { |
| 27 public: | 27 public: |
| 28 ChangeLoweringTest() : simplified_(zone()) {} | 28 ChangeLoweringTest() : simplified_(zone()) {} |
| 29 ~ChangeLoweringTest() OVERRIDE {} | |
| 30 | 29 |
| 31 virtual MachineType WordRepresentation() const = 0; | 30 virtual MachineType WordRepresentation() const = 0; |
| 32 | 31 |
| 33 protected: | 32 protected: |
| 34 int HeapNumberValueOffset() const { | |
| 35 STATIC_ASSERT(HeapNumber::kValueOffset % kApiPointerSize == 0); | |
| 36 return (HeapNumber::kValueOffset / kApiPointerSize) * PointerSize() - | |
| 37 kHeapObjectTag; | |
| 38 } | |
| 39 bool Is32() const { return WordRepresentation() == kRepWord32; } | 33 bool Is32() const { return WordRepresentation() == kRepWord32; } |
| 40 int PointerSize() const { | 34 bool Is64() const { return WordRepresentation() == kRepWord64; } |
| 41 switch (WordRepresentation()) { | |
| 42 case kRepWord32: | |
| 43 return 4; | |
| 44 case kRepWord64: | |
| 45 return 8; | |
| 46 default: | |
| 47 break; | |
| 48 } | |
| 49 UNREACHABLE(); | |
| 50 return 0; | |
| 51 } | |
| 52 int SmiMaxValue() const { return -(SmiMinValue() + 1); } | |
| 53 int SmiMinValue() const { | |
| 54 return static_cast<int>(0xffffffffu << (SmiValueSize() - 1)); | |
| 55 } | |
| 56 int SmiShiftAmount() const { return kSmiTagSize + SmiShiftSize(); } | |
| 57 int SmiShiftSize() const { | |
| 58 return Is32() ? SmiTagging<4>::SmiShiftSize() | |
| 59 : SmiTagging<8>::SmiShiftSize(); | |
| 60 } | |
| 61 int SmiValueSize() const { | |
| 62 return Is32() ? SmiTagging<4>::SmiValueSize() | |
| 63 : SmiTagging<8>::SmiValueSize(); | |
| 64 } | |
| 65 | 35 |
| 66 Reduction Reduce(Node* node) { | 36 Reduction Reduce(Node* node) { |
| 67 MachineOperatorBuilder machine(zone(), WordRepresentation()); | 37 MachineOperatorBuilder machine(zone(), WordRepresentation()); |
| 68 JSOperatorBuilder javascript(zone()); | 38 JSOperatorBuilder javascript(zone()); |
| 69 JSGraph jsgraph(isolate(), graph(), common(), &javascript, &machine); | 39 JSGraph jsgraph(isolate(), graph(), common(), &javascript, &machine); |
| 70 ChangeLowering reducer(&jsgraph); | 40 ChangeLowering reducer(&jsgraph); |
| 71 return reducer.Reduce(node); | 41 return reducer.Reduce(node); |
| 72 } | 42 } |
| 73 | 43 |
| 74 SimplifiedOperatorBuilder* simplified() { return &simplified_; } | 44 SimplifiedOperatorBuilder* simplified() { return &simplified_; } |
| 75 | 45 |
| 76 Matcher<Node*> IsAllocateHeapNumber(const Matcher<Node*>& effect_matcher, | 46 Matcher<Node*> IsAllocateHeapNumber(const Matcher<Node*>& effect_matcher, |
| 77 const Matcher<Node*>& control_matcher) { | 47 const Matcher<Node*>& control_matcher) { |
| 78 return IsCall(_, IsHeapConstant(Unique<HeapObject>::CreateImmovable( | 48 return IsCall(_, IsHeapConstant(Unique<HeapObject>::CreateImmovable( |
| 79 AllocateHeapNumberStub(isolate()).GetCode())), | 49 AllocateHeapNumberStub(isolate()).GetCode())), |
| 80 IsNumberConstant(BitEq(0.0)), effect_matcher, | 50 IsNumberConstant(BitEq(0.0)), effect_matcher, |
| 81 control_matcher); | 51 control_matcher); |
| 82 } | 52 } |
| 53 Matcher<Node*> IsChangeInt32ToSmi(const Matcher<Node*>& value_matcher) { |
| 54 return Is64() ? IsWord64Shl(IsChangeInt32ToInt64(value_matcher), |
| 55 IsSmiShiftBitsConstant()) |
| 56 : IsWord32Shl(value_matcher, IsSmiShiftBitsConstant()); |
| 57 } |
| 58 Matcher<Node*> IsChangeSmiToInt32(const Matcher<Node*>& value_matcher) { |
| 59 return Is64() ? IsTruncateInt64ToInt32( |
| 60 IsWord64Sar(value_matcher, IsSmiShiftBitsConstant())) |
| 61 : IsWord32Sar(value_matcher, IsSmiShiftBitsConstant()); |
| 62 } |
| 63 Matcher<Node*> IsChangeUint32ToSmi(const Matcher<Node*>& value_matcher) { |
| 64 return Is64() ? IsWord64Shl(IsChangeUint32ToUint64(value_matcher), |
| 65 IsSmiShiftBitsConstant()) |
| 66 : IsWord32Shl(value_matcher, IsSmiShiftBitsConstant()); |
| 67 } |
| 83 Matcher<Node*> IsLoadHeapNumber(const Matcher<Node*>& value_matcher, | 68 Matcher<Node*> IsLoadHeapNumber(const Matcher<Node*>& value_matcher, |
| 84 const Matcher<Node*>& control_matcher) { | 69 const Matcher<Node*>& control_matcher) { |
| 85 return IsLoad(kMachFloat64, value_matcher, | 70 return IsLoad(kMachFloat64, value_matcher, |
| 86 IsIntPtrConstant(HeapNumberValueOffset()), graph()->start(), | 71 IsIntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag), |
| 87 control_matcher); | 72 graph()->start(), control_matcher); |
| 88 } | 73 } |
| 89 Matcher<Node*> IsIntPtrConstant(int value) { | 74 Matcher<Node*> IsIntPtrConstant(int value) { |
| 90 return Is32() ? IsInt32Constant(value) : IsInt64Constant(value); | 75 return Is32() ? IsInt32Constant(value) : IsInt64Constant(value); |
| 91 } | 76 } |
| 77 Matcher<Node*> IsSmiShiftBitsConstant() { |
| 78 return IsIntPtrConstant(kSmiShiftSize + kSmiTagSize); |
| 79 } |
| 92 Matcher<Node*> IsWordEqual(const Matcher<Node*>& lhs_matcher, | 80 Matcher<Node*> IsWordEqual(const Matcher<Node*>& lhs_matcher, |
| 93 const Matcher<Node*>& rhs_matcher) { | 81 const Matcher<Node*>& rhs_matcher) { |
| 94 return Is32() ? IsWord32Equal(lhs_matcher, rhs_matcher) | 82 return Is32() ? IsWord32Equal(lhs_matcher, rhs_matcher) |
| 95 : IsWord64Equal(lhs_matcher, rhs_matcher); | 83 : IsWord64Equal(lhs_matcher, rhs_matcher); |
| 96 } | 84 } |
| 97 | 85 |
| 98 private: | 86 private: |
| 99 SimplifiedOperatorBuilder simplified_; | 87 SimplifiedOperatorBuilder simplified_; |
| 100 }; | 88 }; |
| 101 | 89 |
| 102 | 90 |
| 103 // ----------------------------------------------------------------------------- | 91 // ----------------------------------------------------------------------------- |
| 104 // Common. | 92 // Common. |
| 105 | 93 |
| 106 | 94 |
| 107 class ChangeLoweringCommonTest | 95 class ChangeLoweringCommonTest |
| 108 : public ChangeLoweringTest, | 96 : public ChangeLoweringTest, |
| 109 public ::testing::WithParamInterface<MachineType> { | 97 public ::testing::WithParamInterface<MachineType> { |
| 110 public: | 98 public: |
| 111 ~ChangeLoweringCommonTest() OVERRIDE {} | 99 ~ChangeLoweringCommonTest() OVERRIDE {} |
| 112 | 100 |
| 113 MachineType WordRepresentation() const FINAL { return GetParam(); } | 101 MachineType WordRepresentation() const FINAL { return GetParam(); } |
| 114 }; | 102 }; |
| 115 | 103 |
| 116 | 104 |
| 117 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBitToBool) { | 105 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBitToBool) { |
| 118 Node* val = Parameter(0); | 106 Node* value = Parameter(Type::Boolean()); |
| 119 Node* node = graph()->NewNode(simplified()->ChangeBitToBool(), val); | 107 Reduction r = |
| 120 Reduction reduction = Reduce(node); | 108 Reduce(graph()->NewNode(simplified()->ChangeBitToBool(), value)); |
| 121 ASSERT_TRUE(reduction.Changed()); | 109 ASSERT_TRUE(r.Changed()); |
| 122 EXPECT_THAT(reduction.replacement(), | 110 EXPECT_THAT(r.replacement(), IsSelect(kMachAnyTagged, value, IsTrueConstant(), |
| 123 IsSelect(static_cast<MachineType>(kTypeBool | kRepTagged), val, | 111 IsFalseConstant())); |
| 124 IsTrueConstant(), IsFalseConstant())); | |
| 125 } | 112 } |
| 126 | 113 |
| 127 | 114 |
| 128 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBoolToBit) { | 115 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBoolToBit) { |
| 129 Node* val = Parameter(0); | 116 Node* value = Parameter(Type::Number()); |
| 130 Node* node = graph()->NewNode(simplified()->ChangeBoolToBit(), val); | 117 Reduction r = |
| 131 Reduction reduction = Reduce(node); | 118 Reduce(graph()->NewNode(simplified()->ChangeBoolToBit(), value)); |
| 132 ASSERT_TRUE(reduction.Changed()); | 119 ASSERT_TRUE(r.Changed()); |
| 133 | 120 EXPECT_THAT(r.replacement(), IsWordEqual(value, IsTrueConstant())); |
| 134 EXPECT_THAT(reduction.replacement(), IsWordEqual(val, IsTrueConstant())); | |
| 135 } | 121 } |
| 136 | 122 |
| 137 | 123 |
| 138 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeFloat64ToTagged) { | 124 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeFloat64ToTagged) { |
| 139 Node* val = Parameter(0); | 125 Node* value = Parameter(Type::Number()); |
| 140 Node* node = graph()->NewNode(simplified()->ChangeFloat64ToTagged(), val); | 126 Reduction r = |
| 141 Reduction reduction = Reduce(node); | 127 Reduce(graph()->NewNode(simplified()->ChangeFloat64ToTagged(), value)); |
| 142 ASSERT_TRUE(reduction.Changed()); | 128 ASSERT_TRUE(r.Changed()); |
| 143 | |
| 144 Node* finish = reduction.replacement(); | |
| 145 Capture<Node*> heap_number; | 129 Capture<Node*> heap_number; |
| 146 EXPECT_THAT( | 130 EXPECT_THAT( |
| 147 finish, | 131 r.replacement(), |
| 148 IsFinish( | 132 IsFinish( |
| 149 AllOf(CaptureEq(&heap_number), | 133 AllOf(CaptureEq(&heap_number), |
| 150 IsAllocateHeapNumber(IsValueEffect(val), graph()->start())), | 134 IsAllocateHeapNumber(IsValueEffect(value), graph()->start())), |
| 151 IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier), | 135 IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier), |
| 152 CaptureEq(&heap_number), | 136 CaptureEq(&heap_number), |
| 153 IsIntPtrConstant(HeapNumberValueOffset()), val, | 137 IsIntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag), |
| 154 CaptureEq(&heap_number), graph()->start()))); | 138 value, CaptureEq(&heap_number), graph()->start()))); |
| 155 } | 139 } |
| 156 | 140 |
| 157 | 141 |
| 158 TARGET_TEST_P(ChangeLoweringCommonTest, StringAdd) { | 142 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeInt32ToTaggedWithSignedSmall) { |
| 159 Node* node = | 143 Node* value = Parameter(Type::SignedSmall()); |
| 160 graph()->NewNode(simplified()->StringAdd(), Parameter(0), Parameter(1)); | 144 Reduction r = |
| 161 Reduction reduction = Reduce(node); | 145 Reduce(graph()->NewNode(simplified()->ChangeInt32ToTagged(), value)); |
| 162 EXPECT_FALSE(reduction.Changed()); | 146 ASSERT_TRUE(r.Changed()); |
| 147 EXPECT_THAT(r.replacement(), IsChangeInt32ToSmi(value)); |
| 163 } | 148 } |
| 164 | 149 |
| 165 | 150 |
| 151 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeUint32ToTaggedWithUnsignedSmall) { |
| 152 Node* value = Parameter(Type::UnsignedSmall()); |
| 153 Reduction r = |
| 154 Reduce(graph()->NewNode(simplified()->ChangeUint32ToTagged(), value)); |
| 155 ASSERT_TRUE(r.Changed()); |
| 156 EXPECT_THAT(r.replacement(), IsChangeUint32ToSmi(value)); |
| 157 } |
| 158 |
| 159 |
| 160 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToInt32WithTaggedSigned) { |
| 161 Node* value = Parameter(Type::TaggedSigned()); |
| 162 Reduction r = |
| 163 Reduce(graph()->NewNode(simplified()->ChangeTaggedToInt32(), value)); |
| 164 ASSERT_TRUE(r.Changed()); |
| 165 EXPECT_THAT(r.replacement(), IsChangeSmiToInt32(value)); |
| 166 } |
| 167 |
| 168 |
| 169 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToInt32WithTaggedPointer) { |
| 170 Node* value = Parameter(Type::TaggedPointer()); |
| 171 Reduction r = |
| 172 Reduce(graph()->NewNode(simplified()->ChangeTaggedToInt32(), value)); |
| 173 ASSERT_TRUE(r.Changed()); |
| 174 EXPECT_THAT(r.replacement(), IsChangeFloat64ToInt32( |
| 175 IsLoadHeapNumber(value, graph()->start()))); |
| 176 } |
| 177 |
| 178 |
| 179 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToUint32WithTaggedSigned) { |
| 180 Node* value = Parameter(Type::TaggedSigned()); |
| 181 Reduction r = |
| 182 Reduce(graph()->NewNode(simplified()->ChangeTaggedToUint32(), value)); |
| 183 ASSERT_TRUE(r.Changed()); |
| 184 EXPECT_THAT(r.replacement(), IsChangeSmiToInt32(value)); |
| 185 } |
| 186 |
| 187 |
| 188 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToUint32WithTaggedPointer) { |
| 189 Node* value = Parameter(Type::TaggedPointer()); |
| 190 Reduction r = |
| 191 Reduce(graph()->NewNode(simplified()->ChangeTaggedToUint32(), value)); |
| 192 ASSERT_TRUE(r.Changed()); |
| 193 EXPECT_THAT(r.replacement(), IsChangeFloat64ToUint32( |
| 194 IsLoadHeapNumber(value, graph()->start()))); |
| 195 } |
| 196 |
| 197 |
| 166 INSTANTIATE_TEST_CASE_P(ChangeLoweringTest, ChangeLoweringCommonTest, | 198 INSTANTIATE_TEST_CASE_P(ChangeLoweringTest, ChangeLoweringCommonTest, |
| 167 ::testing::Values(kRepWord32, kRepWord64)); | 199 ::testing::Values(kRepWord32, kRepWord64)); |
| 168 | 200 |
| 169 | 201 |
| 170 // ----------------------------------------------------------------------------- | 202 // ----------------------------------------------------------------------------- |
| 171 // 32-bit | 203 // 32-bit |
| 172 | 204 |
| 173 | 205 |
| 174 class ChangeLowering32Test : public ChangeLoweringTest { | 206 class ChangeLowering32Test : public ChangeLoweringTest { |
| 175 public: | 207 public: |
| 176 ~ChangeLowering32Test() OVERRIDE {} | 208 ~ChangeLowering32Test() OVERRIDE {} |
| 177 MachineType WordRepresentation() const FINAL { return kRepWord32; } | 209 MachineType WordRepresentation() const FINAL { return kRepWord32; } |
| 178 }; | 210 }; |
| 179 | 211 |
| 180 | 212 |
| 181 TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTagged) { | 213 TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTagged) { |
| 182 Node* val = Parameter(0); | 214 Node* value = Parameter(Type::Integral32()); |
| 183 Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), val); | 215 Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), value); |
| 184 NodeProperties::SetBounds(val, Bounds(Type::None(), Type::Integral32())); | 216 Reduction r = Reduce(node); |
| 185 Reduction reduction = Reduce(node); | 217 ASSERT_TRUE(r.Changed()); |
| 186 ASSERT_TRUE(reduction.Changed()); | |
| 187 | |
| 188 Node* phi = reduction.replacement(); | |
| 189 Capture<Node*> add, branch, heap_number, if_true; | 218 Capture<Node*> add, branch, heap_number, if_true; |
| 190 EXPECT_THAT( | 219 EXPECT_THAT( |
| 191 phi, | 220 r.replacement(), |
| 192 IsPhi(kMachAnyTagged, | 221 IsPhi(kMachAnyTagged, |
| 193 IsFinish(AllOf(CaptureEq(&heap_number), | 222 IsFinish(AllOf(CaptureEq(&heap_number), |
| 194 IsAllocateHeapNumber(_, CaptureEq(&if_true))), | 223 IsAllocateHeapNumber(_, CaptureEq(&if_true))), |
| 195 IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier), | 224 IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier), |
| 196 CaptureEq(&heap_number), | 225 CaptureEq(&heap_number), |
| 197 IsIntPtrConstant(HeapNumberValueOffset()), | 226 IsIntPtrConstant(HeapNumber::kValueOffset - |
| 198 IsChangeInt32ToFloat64(val), | 227 kHeapObjectTag), |
| 228 IsChangeInt32ToFloat64(value), |
| 199 CaptureEq(&heap_number), CaptureEq(&if_true))), | 229 CaptureEq(&heap_number), CaptureEq(&if_true))), |
| 200 IsProjection( | 230 IsProjection(0, AllOf(CaptureEq(&add), |
| 201 0, AllOf(CaptureEq(&add), IsInt32AddWithOverflow(val, val))), | 231 IsInt32AddWithOverflow(value, value))), |
| 202 IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))), | 232 IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))), |
| 203 IsIfFalse(AllOf(CaptureEq(&branch), | 233 IsIfFalse(AllOf(CaptureEq(&branch), |
| 204 IsBranch(IsProjection(1, CaptureEq(&add)), | 234 IsBranch(IsProjection(1, CaptureEq(&add)), |
| 205 graph()->start())))))); | 235 graph()->start())))))); |
| 206 } | 236 } |
| 207 | 237 |
| 208 | 238 |
| 209 TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTaggedSmall) { | |
| 210 Node* val = Parameter(0); | |
| 211 Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), val); | |
| 212 NodeProperties::SetBounds(val, Bounds(Type::None(), Type::SignedSmall())); | |
| 213 Reduction reduction = Reduce(node); | |
| 214 ASSERT_TRUE(reduction.Changed()); | |
| 215 | |
| 216 Node* change = reduction.replacement(); | |
| 217 Capture<Node*> add, branch, heap_number, if_true; | |
| 218 EXPECT_THAT(change, IsWord32Shl(val, IsInt32Constant(SmiShiftAmount()))); | |
| 219 } | |
| 220 | |
| 221 | |
| 222 TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToFloat64) { | 239 TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToFloat64) { |
| 223 STATIC_ASSERT(kSmiTag == 0); | 240 STATIC_ASSERT(kSmiTag == 0); |
| 224 STATIC_ASSERT(kSmiTagSize == 1); | 241 STATIC_ASSERT(kSmiTagSize == 1); |
| 225 | 242 |
| 226 Node* val = Parameter(0); | 243 Node* value = Parameter(Type::Number()); |
| 227 Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), val); | 244 Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), value); |
| 228 Reduction reduction = Reduce(node); | 245 Reduction r = Reduce(node); |
| 229 ASSERT_TRUE(reduction.Changed()); | 246 ASSERT_TRUE(r.Changed()); |
| 230 | |
| 231 Node* phi = reduction.replacement(); | |
| 232 Capture<Node*> branch, if_true; | 247 Capture<Node*> branch, if_true; |
| 233 EXPECT_THAT( | 248 EXPECT_THAT( |
| 234 phi, | 249 r.replacement(), |
| 235 IsPhi( | 250 IsPhi(kMachFloat64, IsLoadHeapNumber(value, CaptureEq(&if_true)), |
| 236 kMachFloat64, IsLoadHeapNumber(val, CaptureEq(&if_true)), | 251 IsChangeInt32ToFloat64(IsWord32Sar( |
| 237 IsChangeInt32ToFloat64( | 252 value, IsInt32Constant(kSmiTagSize + kSmiShiftSize))), |
| 238 IsWord32Sar(val, IsInt32Constant(SmiShiftAmount()))), | 253 IsMerge(AllOf(CaptureEq(&if_true), |
| 239 IsMerge( | 254 IsIfTrue(AllOf( |
| 240 AllOf(CaptureEq(&if_true), | 255 CaptureEq(&branch), |
| 241 IsIfTrue(AllOf( | 256 IsBranch(IsWord32And( |
| 242 CaptureEq(&branch), | 257 value, IsInt32Constant(kSmiTagMask)), |
| 243 IsBranch(IsWord32And(val, IsInt32Constant(kSmiTagMask)), | 258 graph()->start())))), |
| 244 graph()->start())))), | 259 IsIfFalse(CaptureEq(&branch))))); |
| 245 IsIfFalse(CaptureEq(&branch))))); | |
| 246 } | 260 } |
| 247 | 261 |
| 248 | 262 |
| 249 TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToInt32) { | 263 TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToInt32) { |
| 250 STATIC_ASSERT(kSmiTag == 0); | 264 STATIC_ASSERT(kSmiTag == 0); |
| 251 STATIC_ASSERT(kSmiTagSize == 1); | 265 STATIC_ASSERT(kSmiTagSize == 1); |
| 252 | 266 |
| 253 Node* val = Parameter(0); | 267 Node* value = Parameter(Type::Signed32()); |
| 254 Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), val); | 268 Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), value); |
| 255 Reduction reduction = Reduce(node); | 269 Reduction r = Reduce(node); |
| 256 ASSERT_TRUE(reduction.Changed()); | 270 ASSERT_TRUE(r.Changed()); |
| 257 | |
| 258 Node* phi = reduction.replacement(); | |
| 259 Capture<Node*> branch, if_true; | 271 Capture<Node*> branch, if_true; |
| 260 EXPECT_THAT( | 272 EXPECT_THAT( |
| 261 phi, | 273 r.replacement(), |
| 262 IsPhi(kMachInt32, | 274 IsPhi( |
| 263 IsChangeFloat64ToInt32(IsLoadHeapNumber(val, CaptureEq(&if_true))), | 275 kMachInt32, |
| 264 IsWord32Sar(val, IsInt32Constant(SmiShiftAmount())), | 276 IsChangeFloat64ToInt32(IsLoadHeapNumber(value, CaptureEq(&if_true))), |
| 265 IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))), | 277 IsWord32Sar(value, IsInt32Constant(kSmiTagSize + kSmiShiftSize)), |
| 266 IsIfFalse(AllOf( | 278 IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))), |
| 267 CaptureEq(&branch), | 279 IsIfFalse(AllOf( |
| 268 IsBranch(IsWord32And(val, IsInt32Constant(kSmiTagMask)), | 280 CaptureEq(&branch), |
| 269 graph()->start())))))); | 281 IsBranch(IsWord32And(value, IsInt32Constant(kSmiTagMask)), |
| 282 graph()->start())))))); |
| 270 } | 283 } |
| 271 | 284 |
| 272 | 285 |
| 273 TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToUint32) { | 286 TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToUint32) { |
| 274 STATIC_ASSERT(kSmiTag == 0); | 287 STATIC_ASSERT(kSmiTag == 0); |
| 275 STATIC_ASSERT(kSmiTagSize == 1); | 288 STATIC_ASSERT(kSmiTagSize == 1); |
| 276 | 289 |
| 277 Node* val = Parameter(0); | 290 Node* value = Parameter(Type::Unsigned32()); |
| 278 Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), val); | 291 Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), value); |
| 279 Reduction reduction = Reduce(node); | 292 Reduction r = Reduce(node); |
| 280 ASSERT_TRUE(reduction.Changed()); | 293 ASSERT_TRUE(r.Changed()); |
| 281 | |
| 282 Node* phi = reduction.replacement(); | |
| 283 Capture<Node*> branch, if_true; | 294 Capture<Node*> branch, if_true; |
| 284 EXPECT_THAT( | 295 EXPECT_THAT( |
| 285 phi, | 296 r.replacement(), |
| 286 IsPhi(kMachUint32, | 297 IsPhi( |
| 287 IsChangeFloat64ToUint32(IsLoadHeapNumber(val, CaptureEq(&if_true))), | 298 kMachUint32, |
| 288 IsWord32Sar(val, IsInt32Constant(SmiShiftAmount())), | 299 IsChangeFloat64ToUint32(IsLoadHeapNumber(value, CaptureEq(&if_true))), |
| 289 IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))), | 300 IsWord32Sar(value, IsInt32Constant(kSmiTagSize + kSmiShiftSize)), |
| 290 IsIfFalse(AllOf( | 301 IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))), |
| 291 CaptureEq(&branch), | 302 IsIfFalse(AllOf( |
| 292 IsBranch(IsWord32And(val, IsInt32Constant(kSmiTagMask)), | 303 CaptureEq(&branch), |
| 293 graph()->start())))))); | 304 IsBranch(IsWord32And(value, IsInt32Constant(kSmiTagMask)), |
| 305 graph()->start())))))); |
| 294 } | 306 } |
| 295 | 307 |
| 296 | 308 |
| 297 TARGET_TEST_F(ChangeLowering32Test, ChangeUint32ToTagged) { | 309 TARGET_TEST_F(ChangeLowering32Test, ChangeUint32ToTagged) { |
| 298 STATIC_ASSERT(kSmiTag == 0); | 310 STATIC_ASSERT(kSmiTag == 0); |
| 299 STATIC_ASSERT(kSmiTagSize == 1); | 311 STATIC_ASSERT(kSmiTagSize == 1); |
| 300 | 312 |
| 301 Node* val = Parameter(0); | 313 Node* value = Parameter(Type::Number()); |
| 302 Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), val); | 314 Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), value); |
| 303 Reduction reduction = Reduce(node); | 315 Reduction r = Reduce(node); |
| 304 ASSERT_TRUE(reduction.Changed()); | 316 ASSERT_TRUE(r.Changed()); |
| 305 | |
| 306 Node* phi = reduction.replacement(); | |
| 307 Capture<Node*> branch, heap_number, if_false; | 317 Capture<Node*> branch, heap_number, if_false; |
| 308 EXPECT_THAT( | 318 EXPECT_THAT( |
| 309 phi, | 319 r.replacement(), |
| 310 IsPhi( | 320 IsPhi( |
| 311 kMachAnyTagged, IsWord32Shl(val, IsInt32Constant(SmiShiftAmount())), | 321 kMachAnyTagged, |
| 322 IsWord32Shl(value, IsInt32Constant(kSmiTagSize + kSmiShiftSize)), |
| 312 IsFinish(AllOf(CaptureEq(&heap_number), | 323 IsFinish(AllOf(CaptureEq(&heap_number), |
| 313 IsAllocateHeapNumber(_, CaptureEq(&if_false))), | 324 IsAllocateHeapNumber(_, CaptureEq(&if_false))), |
| 314 IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier), | 325 IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier), |
| 315 CaptureEq(&heap_number), | 326 CaptureEq(&heap_number), |
| 316 IsInt32Constant(HeapNumberValueOffset()), | 327 IsInt32Constant(HeapNumber::kValueOffset - |
| 317 IsChangeUint32ToFloat64(val), | 328 kHeapObjectTag), |
| 329 IsChangeUint32ToFloat64(value), |
| 318 CaptureEq(&heap_number), CaptureEq(&if_false))), | 330 CaptureEq(&heap_number), CaptureEq(&if_false))), |
| 319 IsMerge( | 331 IsMerge(IsIfTrue(AllOf( |
| 320 IsIfTrue(AllOf(CaptureEq(&branch), | 332 CaptureEq(&branch), |
| 321 IsBranch(IsUint32LessThanOrEqual( | 333 IsBranch(IsUint32LessThanOrEqual( |
| 322 val, IsInt32Constant(SmiMaxValue())), | 334 value, IsInt32Constant(Smi::kMaxValue)), |
| 323 graph()->start()))), | 335 graph()->start()))), |
| 324 AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch)))))); | 336 AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch)))))); |
| 325 } | 337 } |
| 326 | 338 |
| 327 | 339 |
| 328 // ----------------------------------------------------------------------------- | 340 // ----------------------------------------------------------------------------- |
| 329 // 64-bit | 341 // 64-bit |
| 330 | 342 |
| 331 | 343 |
| 332 class ChangeLowering64Test : public ChangeLoweringTest { | 344 class ChangeLowering64Test : public ChangeLoweringTest { |
| 333 public: | 345 public: |
| 334 ~ChangeLowering64Test() OVERRIDE {} | 346 ~ChangeLowering64Test() OVERRIDE {} |
| 335 MachineType WordRepresentation() const FINAL { return kRepWord64; } | 347 MachineType WordRepresentation() const FINAL { return kRepWord64; } |
| 336 }; | 348 }; |
| 337 | 349 |
| 338 | 350 |
| 339 TARGET_TEST_F(ChangeLowering64Test, ChangeInt32ToTagged) { | 351 TARGET_TEST_F(ChangeLowering64Test, ChangeInt32ToTagged) { |
| 340 Node* val = Parameter(0); | 352 Node* value = Parameter(Type::Signed32()); |
| 341 Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), val); | 353 Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), value); |
| 342 Reduction reduction = Reduce(node); | 354 Reduction r = Reduce(node); |
| 343 ASSERT_TRUE(reduction.Changed()); | 355 ASSERT_TRUE(r.Changed()); |
| 344 | 356 EXPECT_THAT(r.replacement(), IsChangeInt32ToSmi(value)); |
| 345 EXPECT_THAT(reduction.replacement(), | |
| 346 IsWord64Shl(IsChangeInt32ToInt64(val), | |
| 347 IsInt64Constant(SmiShiftAmount()))); | |
| 348 } | 357 } |
| 349 | 358 |
| 350 | 359 |
| 351 TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToFloat64) { | 360 TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToFloat64) { |
| 352 STATIC_ASSERT(kSmiTag == 0); | 361 STATIC_ASSERT(kSmiTag == 0); |
| 353 STATIC_ASSERT(kSmiTagSize == 1); | 362 STATIC_ASSERT(kSmiTagSize == 1); |
| 354 | 363 |
| 355 Node* val = Parameter(0); | 364 Node* value = Parameter(Type::Number()); |
| 356 Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), val); | 365 Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), value); |
| 357 Reduction reduction = Reduce(node); | 366 Reduction r = Reduce(node); |
| 358 ASSERT_TRUE(reduction.Changed()); | 367 ASSERT_TRUE(r.Changed()); |
| 359 | |
| 360 Node* phi = reduction.replacement(); | |
| 361 Capture<Node*> branch, if_true; | 368 Capture<Node*> branch, if_true; |
| 362 EXPECT_THAT( | 369 EXPECT_THAT( |
| 363 phi, | 370 r.replacement(), |
| 364 IsPhi( | 371 IsPhi(kMachFloat64, IsLoadHeapNumber(value, CaptureEq(&if_true)), |
| 365 kMachFloat64, IsLoadHeapNumber(val, CaptureEq(&if_true)), | 372 IsChangeInt32ToFloat64(IsTruncateInt64ToInt32(IsWord64Sar( |
| 366 IsChangeInt32ToFloat64(IsTruncateInt64ToInt32( | 373 value, IsInt64Constant(kSmiTagSize + kSmiShiftSize)))), |
| 367 IsWord64Sar(val, IsInt64Constant(SmiShiftAmount())))), | 374 IsMerge(AllOf(CaptureEq(&if_true), |
| 368 IsMerge( | 375 IsIfTrue(AllOf( |
| 369 AllOf(CaptureEq(&if_true), | 376 CaptureEq(&branch), |
| 370 IsIfTrue(AllOf( | 377 IsBranch(IsWord64And( |
| 371 CaptureEq(&branch), | 378 value, IsInt64Constant(kSmiTagMask)), |
| 372 IsBranch(IsWord64And(val, IsInt64Constant(kSmiTagMask)), | 379 graph()->start())))), |
| 373 graph()->start())))), | 380 IsIfFalse(CaptureEq(&branch))))); |
| 374 IsIfFalse(CaptureEq(&branch))))); | |
| 375 } | 381 } |
| 376 | 382 |
| 377 | 383 |
| 378 TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToInt32) { | 384 TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToInt32) { |
| 379 STATIC_ASSERT(kSmiTag == 0); | 385 STATIC_ASSERT(kSmiTag == 0); |
| 380 STATIC_ASSERT(kSmiTagSize == 1); | 386 STATIC_ASSERT(kSmiTagSize == 1); |
| 381 | 387 |
| 382 Node* val = Parameter(0); | 388 Node* value = Parameter(Type::Signed32()); |
| 383 Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), val); | 389 Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), value); |
| 384 Reduction reduction = Reduce(node); | 390 Reduction r = Reduce(node); |
| 385 ASSERT_TRUE(reduction.Changed()); | 391 ASSERT_TRUE(r.Changed()); |
| 386 | |
| 387 Node* phi = reduction.replacement(); | |
| 388 Capture<Node*> branch, if_true; | 392 Capture<Node*> branch, if_true; |
| 389 EXPECT_THAT( | 393 EXPECT_THAT( |
| 390 phi, | 394 r.replacement(), |
| 391 IsPhi(kMachInt32, | 395 IsPhi( |
| 392 IsChangeFloat64ToInt32(IsLoadHeapNumber(val, CaptureEq(&if_true))), | 396 kMachInt32, |
| 393 IsTruncateInt64ToInt32( | 397 IsChangeFloat64ToInt32(IsLoadHeapNumber(value, CaptureEq(&if_true))), |
| 394 IsWord64Sar(val, IsInt64Constant(SmiShiftAmount()))), | 398 IsTruncateInt64ToInt32( |
| 395 IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))), | 399 IsWord64Sar(value, IsInt64Constant(kSmiTagSize + kSmiShiftSize))), |
| 396 IsIfFalse(AllOf( | 400 IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))), |
| 397 CaptureEq(&branch), | 401 IsIfFalse(AllOf( |
| 398 IsBranch(IsWord64And(val, IsInt64Constant(kSmiTagMask)), | 402 CaptureEq(&branch), |
| 399 graph()->start())))))); | 403 IsBranch(IsWord64And(value, IsInt64Constant(kSmiTagMask)), |
| 404 graph()->start())))))); |
| 400 } | 405 } |
| 401 | 406 |
| 402 | 407 |
| 403 TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToUint32) { | 408 TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToUint32) { |
| 404 STATIC_ASSERT(kSmiTag == 0); | 409 STATIC_ASSERT(kSmiTag == 0); |
| 405 STATIC_ASSERT(kSmiTagSize == 1); | 410 STATIC_ASSERT(kSmiTagSize == 1); |
| 406 | 411 |
| 407 Node* val = Parameter(0); | 412 Node* value = Parameter(Type::Unsigned32()); |
| 408 Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), val); | 413 Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), value); |
| 409 Reduction reduction = Reduce(node); | 414 Reduction r = Reduce(node); |
| 410 ASSERT_TRUE(reduction.Changed()); | 415 ASSERT_TRUE(r.Changed()); |
| 411 | |
| 412 Node* phi = reduction.replacement(); | |
| 413 Capture<Node*> branch, if_true; | 416 Capture<Node*> branch, if_true; |
| 414 EXPECT_THAT( | 417 EXPECT_THAT( |
| 415 phi, | 418 r.replacement(), |
| 416 IsPhi(kMachUint32, | 419 IsPhi( |
| 417 IsChangeFloat64ToUint32(IsLoadHeapNumber(val, CaptureEq(&if_true))), | 420 kMachUint32, |
| 418 IsTruncateInt64ToInt32( | 421 IsChangeFloat64ToUint32(IsLoadHeapNumber(value, CaptureEq(&if_true))), |
| 419 IsWord64Sar(val, IsInt64Constant(SmiShiftAmount()))), | 422 IsTruncateInt64ToInt32( |
| 420 IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))), | 423 IsWord64Sar(value, IsInt64Constant(kSmiTagSize + kSmiShiftSize))), |
| 421 IsIfFalse(AllOf( | 424 IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))), |
| 422 CaptureEq(&branch), | 425 IsIfFalse(AllOf( |
| 423 IsBranch(IsWord64And(val, IsInt64Constant(kSmiTagMask)), | 426 CaptureEq(&branch), |
| 424 graph()->start())))))); | 427 IsBranch(IsWord64And(value, IsInt64Constant(kSmiTagMask)), |
| 428 graph()->start())))))); |
| 425 } | 429 } |
| 426 | 430 |
| 427 | 431 |
| 428 TARGET_TEST_F(ChangeLowering64Test, ChangeUint32ToTagged) { | 432 TARGET_TEST_F(ChangeLowering64Test, ChangeUint32ToTagged) { |
| 429 STATIC_ASSERT(kSmiTag == 0); | 433 STATIC_ASSERT(kSmiTag == 0); |
| 430 STATIC_ASSERT(kSmiTagSize == 1); | 434 STATIC_ASSERT(kSmiTagSize == 1); |
| 431 | 435 |
| 432 Node* val = Parameter(0); | 436 Node* value = Parameter(Type::Number()); |
| 433 Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), val); | 437 Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), value); |
| 434 Reduction reduction = Reduce(node); | 438 Reduction r = Reduce(node); |
| 435 ASSERT_TRUE(reduction.Changed()); | 439 ASSERT_TRUE(r.Changed()); |
| 436 | |
| 437 Node* phi = reduction.replacement(); | |
| 438 Capture<Node*> branch, heap_number, if_false; | 440 Capture<Node*> branch, heap_number, if_false; |
| 439 EXPECT_THAT( | 441 EXPECT_THAT( |
| 440 phi, | 442 r.replacement(), |
| 441 IsPhi( | 443 IsPhi( |
| 442 kMachAnyTagged, IsWord64Shl(IsChangeUint32ToUint64(val), | 444 kMachAnyTagged, |
| 443 IsInt64Constant(SmiShiftAmount())), | 445 IsWord64Shl(IsChangeUint32ToUint64(value), |
| 446 IsInt64Constant(kSmiTagSize + kSmiShiftSize)), |
| 444 IsFinish(AllOf(CaptureEq(&heap_number), | 447 IsFinish(AllOf(CaptureEq(&heap_number), |
| 445 IsAllocateHeapNumber(_, CaptureEq(&if_false))), | 448 IsAllocateHeapNumber(_, CaptureEq(&if_false))), |
| 446 IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier), | 449 IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier), |
| 447 CaptureEq(&heap_number), | 450 CaptureEq(&heap_number), |
| 448 IsInt64Constant(HeapNumberValueOffset()), | 451 IsInt64Constant(HeapNumber::kValueOffset - |
| 449 IsChangeUint32ToFloat64(val), | 452 kHeapObjectTag), |
| 453 IsChangeUint32ToFloat64(value), |
| 450 CaptureEq(&heap_number), CaptureEq(&if_false))), | 454 CaptureEq(&heap_number), CaptureEq(&if_false))), |
| 451 IsMerge( | 455 IsMerge(IsIfTrue(AllOf( |
| 452 IsIfTrue(AllOf(CaptureEq(&branch), | 456 CaptureEq(&branch), |
| 453 IsBranch(IsUint32LessThanOrEqual( | 457 IsBranch(IsUint32LessThanOrEqual( |
| 454 val, IsInt32Constant(SmiMaxValue())), | 458 value, IsInt32Constant(Smi::kMaxValue)), |
| 455 graph()->start()))), | 459 graph()->start()))), |
| 456 AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch)))))); | 460 AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch)))))); |
| 457 } | 461 } |
| 458 | 462 |
| 459 } // namespace compiler | 463 } // namespace compiler |
| 460 } // namespace internal | 464 } // namespace internal |
| 461 } // namespace v8 | 465 } // namespace v8 |
| OLD | NEW |