OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "src/code-stubs.h" | |
6 #include "src/compiler/change-lowering.h" | |
7 #include "src/compiler/js-graph.h" | |
8 #include "src/compiler/linkage.h" | |
9 #include "src/compiler/node-properties.h" | |
10 #include "src/compiler/simplified-operator.h" | |
11 #include "test/unittests/compiler/compiler-test-utils.h" | |
12 #include "test/unittests/compiler/graph-unittest.h" | |
13 #include "test/unittests/compiler/node-test-utils.h" | |
14 #include "testing/gmock-support.h" | |
15 | |
16 using testing::_; | |
17 using testing::AllOf; | |
18 using testing::BitEq; | |
19 using testing::Capture; | |
20 using testing::CaptureEq; | |
21 | |
22 namespace v8 { | |
23 namespace internal { | |
24 namespace compiler { | |
25 | |
26 class ChangeLoweringTest : public TypedGraphTest { | |
27 public: | |
28 ChangeLoweringTest() : simplified_(zone()) {} | |
29 | |
30 virtual MachineRepresentation WordRepresentation() const = 0; | |
31 | |
32 protected: | |
33 bool Is32() const { | |
34 return WordRepresentation() == MachineRepresentation::kWord32; | |
35 } | |
36 bool Is64() const { | |
37 return WordRepresentation() == MachineRepresentation::kWord64; | |
38 } | |
39 | |
40 Reduction Reduce(Node* node) { | |
41 GraphReducer graph_reducer(zone(), graph()); | |
42 MachineOperatorBuilder machine(zone(), WordRepresentation()); | |
43 JSOperatorBuilder javascript(zone()); | |
44 JSGraph jsgraph(isolate(), graph(), common(), &javascript, nullptr, | |
45 &machine); | |
46 ChangeLowering reducer(&graph_reducer, &jsgraph); | |
47 return reducer.Reduce(node); | |
48 } | |
49 | |
50 SimplifiedOperatorBuilder* simplified() { return &simplified_; } | |
51 | |
52 Matcher<Node*> IsAllocateHeapNumber(const Matcher<Node*>& effect_matcher, | |
53 const Matcher<Node*>& control_matcher) { | |
54 return IsCall( | |
55 _, IsHeapConstant(AllocateHeapNumberStub(isolate()).GetCode()), | |
56 IsNumberConstant(BitEq(0.0)), effect_matcher, control_matcher); | |
57 } | |
58 Matcher<Node*> IsChangeInt32ToSmi(const Matcher<Node*>& value_matcher) { | |
59 return Is64() ? IsWord64Shl(IsChangeInt32ToInt64(value_matcher), | |
60 IsSmiShiftBitsConstant()) | |
61 : IsWord32Shl(value_matcher, IsSmiShiftBitsConstant()); | |
62 } | |
63 Matcher<Node*> IsChangeSmiToInt32(const Matcher<Node*>& value_matcher) { | |
64 return Is64() ? IsTruncateInt64ToInt32( | |
65 IsWord64Sar(value_matcher, IsSmiShiftBitsConstant())) | |
66 : IsWord32Sar(value_matcher, IsSmiShiftBitsConstant()); | |
67 } | |
68 Matcher<Node*> IsChangeUint32ToSmi(const Matcher<Node*>& value_matcher) { | |
69 return Is64() ? IsWord64Shl(IsChangeUint32ToUint64(value_matcher), | |
70 IsSmiShiftBitsConstant()) | |
71 : IsWord32Shl(value_matcher, IsSmiShiftBitsConstant()); | |
72 } | |
73 Matcher<Node*> IsLoadHeapNumber(const Matcher<Node*>& value_matcher, | |
74 const Matcher<Node*>& control_matcher) { | |
75 return IsLoad(MachineType::Float64(), value_matcher, | |
76 IsIntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag), | |
77 graph()->start(), control_matcher); | |
78 } | |
79 Matcher<Node*> IsIntPtrConstant(int value) { | |
80 return Is32() ? IsInt32Constant(value) : IsInt64Constant(value); | |
81 } | |
82 Matcher<Node*> IsSmiShiftBitsConstant() { | |
83 return IsIntPtrConstant(kSmiShiftSize + kSmiTagSize); | |
84 } | |
85 Matcher<Node*> IsWordEqual(const Matcher<Node*>& lhs_matcher, | |
86 const Matcher<Node*>& rhs_matcher) { | |
87 return Is32() ? IsWord32Equal(lhs_matcher, rhs_matcher) | |
88 : IsWord64Equal(lhs_matcher, rhs_matcher); | |
89 } | |
90 | |
91 private: | |
92 SimplifiedOperatorBuilder simplified_; | |
93 }; | |
94 | |
95 | |
96 // ----------------------------------------------------------------------------- | |
97 // Common. | |
98 | |
99 | |
100 class ChangeLoweringCommonTest | |
101 : public ChangeLoweringTest, | |
102 public ::testing::WithParamInterface<MachineRepresentation> { | |
103 public: | |
104 ~ChangeLoweringCommonTest() override {} | |
105 | |
106 MachineRepresentation WordRepresentation() const final { return GetParam(); } | |
107 }; | |
108 | |
109 TARGET_TEST_P(ChangeLoweringCommonTest, StoreFieldSmi) { | |
110 FieldAccess access = { | |
111 kTaggedBase, FixedArrayBase::kHeaderSize, Handle<Name>::null(), | |
112 Type::Any(), MachineType::AnyTagged(), kNoWriteBarrier}; | |
113 Node* p0 = Parameter(Type::TaggedPointer()); | |
114 Node* p1 = Parameter(Type::TaggedSigned()); | |
115 Node* store = graph()->NewNode(simplified()->StoreField(access), p0, p1, | |
116 graph()->start(), graph()->start()); | |
117 Reduction r = Reduce(store); | |
118 | |
119 ASSERT_TRUE(r.Changed()); | |
120 EXPECT_THAT(r.replacement(), | |
121 IsStore(StoreRepresentation(MachineRepresentation::kTagged, | |
122 kNoWriteBarrier), | |
123 p0, IsIntPtrConstant(access.offset - access.tag()), p1, | |
124 graph()->start(), graph()->start())); | |
125 } | |
126 | |
127 | |
128 TARGET_TEST_P(ChangeLoweringCommonTest, StoreFieldTagged) { | |
129 FieldAccess access = { | |
130 kTaggedBase, FixedArrayBase::kHeaderSize, Handle<Name>::null(), | |
131 Type::Any(), MachineType::AnyTagged(), kFullWriteBarrier}; | |
132 Node* p0 = Parameter(Type::TaggedPointer()); | |
133 Node* p1 = Parameter(Type::Tagged()); | |
134 Node* store = graph()->NewNode(simplified()->StoreField(access), p0, p1, | |
135 graph()->start(), graph()->start()); | |
136 Reduction r = Reduce(store); | |
137 | |
138 ASSERT_TRUE(r.Changed()); | |
139 EXPECT_THAT(r.replacement(), | |
140 IsStore(StoreRepresentation(MachineRepresentation::kTagged, | |
141 kFullWriteBarrier), | |
142 p0, IsIntPtrConstant(access.offset - access.tag()), p1, | |
143 graph()->start(), graph()->start())); | |
144 } | |
145 | |
146 | |
147 TARGET_TEST_P(ChangeLoweringCommonTest, LoadField) { | |
148 FieldAccess access = { | |
149 kTaggedBase, FixedArrayBase::kHeaderSize, Handle<Name>::null(), | |
150 Type::Any(), MachineType::AnyTagged(), kNoWriteBarrier}; | |
151 Node* p0 = Parameter(Type::TaggedPointer()); | |
152 Node* load = graph()->NewNode(simplified()->LoadField(access), p0, | |
153 graph()->start(), graph()->start()); | |
154 Reduction r = Reduce(load); | |
155 | |
156 ASSERT_TRUE(r.Changed()); | |
157 Matcher<Node*> index_match = IsIntPtrConstant(access.offset - access.tag()); | |
158 EXPECT_THAT(r.replacement(), | |
159 IsLoad(MachineType::AnyTagged(), p0, | |
160 IsIntPtrConstant(access.offset - access.tag()), | |
161 graph()->start(), graph()->start())); | |
162 } | |
163 | |
164 | |
165 TARGET_TEST_P(ChangeLoweringCommonTest, StoreElementTagged) { | |
166 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), | |
167 MachineType::AnyTagged(), kFullWriteBarrier}; | |
168 Node* p0 = Parameter(Type::TaggedPointer()); | |
169 Node* p1 = Parameter(Type::Signed32()); | |
170 Node* p2 = Parameter(Type::Tagged()); | |
171 Node* store = graph()->NewNode(simplified()->StoreElement(access), p0, p1, p2, | |
172 graph()->start(), graph()->start()); | |
173 Reduction r = Reduce(store); | |
174 | |
175 const int element_size_shift = | |
176 ElementSizeLog2Of(access.machine_type.representation()); | |
177 ASSERT_TRUE(r.Changed()); | |
178 Matcher<Node*> index_match = | |
179 IsInt32Add(IsWord32Shl(p1, IsInt32Constant(element_size_shift)), | |
180 IsInt32Constant(access.header_size - access.tag())); | |
181 if (!Is32()) { | |
182 index_match = IsChangeUint32ToUint64(index_match); | |
183 } | |
184 | |
185 EXPECT_THAT(r.replacement(), | |
186 IsStore(StoreRepresentation(MachineRepresentation::kTagged, | |
187 kFullWriteBarrier), | |
188 p0, index_match, p2, graph()->start(), graph()->start())); | |
189 } | |
190 | |
191 | |
192 TARGET_TEST_P(ChangeLoweringCommonTest, StoreElementUint8) { | |
193 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | |
194 Type::Signed32(), MachineType::Uint8(), | |
195 kNoWriteBarrier}; | |
196 Node* p0 = Parameter(Type::TaggedPointer()); | |
197 Node* p1 = Parameter(Type::Signed32()); | |
198 Node* p2 = Parameter(Type::Signed32()); | |
199 Node* store = graph()->NewNode(simplified()->StoreElement(access), p0, p1, p2, | |
200 graph()->start(), graph()->start()); | |
201 Reduction r = Reduce(store); | |
202 | |
203 ASSERT_TRUE(r.Changed()); | |
204 Matcher<Node*> index_match = | |
205 IsInt32Add(p1, IsInt32Constant(access.header_size - access.tag())); | |
206 if (!Is32()) { | |
207 index_match = IsChangeUint32ToUint64(index_match); | |
208 } | |
209 | |
210 EXPECT_THAT(r.replacement(), | |
211 IsStore(StoreRepresentation(MachineRepresentation::kWord8, | |
212 kNoWriteBarrier), | |
213 p0, index_match, p2, graph()->start(), graph()->start())); | |
214 } | |
215 | |
216 | |
217 TARGET_TEST_P(ChangeLoweringCommonTest, LoadElementTagged) { | |
218 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(), | |
219 MachineType::AnyTagged(), kNoWriteBarrier}; | |
220 Node* p0 = Parameter(Type::TaggedPointer()); | |
221 Node* p1 = Parameter(Type::Signed32()); | |
222 Node* load = graph()->NewNode(simplified()->LoadElement(access), p0, p1, | |
223 graph()->start(), graph()->start()); | |
224 Reduction r = Reduce(load); | |
225 | |
226 const int element_size_shift = | |
227 ElementSizeLog2Of(access.machine_type.representation()); | |
228 ASSERT_TRUE(r.Changed()); | |
229 Matcher<Node*> index_match = | |
230 IsInt32Add(IsWord32Shl(p1, IsInt32Constant(element_size_shift)), | |
231 IsInt32Constant(access.header_size - access.tag())); | |
232 if (!Is32()) { | |
233 index_match = IsChangeUint32ToUint64(index_match); | |
234 } | |
235 | |
236 EXPECT_THAT(r.replacement(), IsLoad(MachineType::AnyTagged(), p0, index_match, | |
237 graph()->start(), graph()->start())); | |
238 } | |
239 | |
240 | |
241 TARGET_TEST_P(ChangeLoweringCommonTest, LoadElementInt8) { | |
242 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, | |
243 Type::Signed32(), MachineType::Int8(), | |
244 kNoWriteBarrier}; | |
245 Node* p0 = Parameter(Type::TaggedPointer()); | |
246 Node* p1 = Parameter(Type::Signed32()); | |
247 Node* load = graph()->NewNode(simplified()->LoadElement(access), p0, p1, | |
248 graph()->start(), graph()->start()); | |
249 Reduction r = Reduce(load); | |
250 | |
251 ASSERT_TRUE(r.Changed()); | |
252 Matcher<Node*> index_match = | |
253 IsInt32Add(p1, IsInt32Constant(access.header_size - access.tag())); | |
254 if (!Is32()) { | |
255 index_match = IsChangeUint32ToUint64(index_match); | |
256 } | |
257 | |
258 EXPECT_THAT(r.replacement(), IsLoad(MachineType::Int8(), p0, index_match, | |
259 graph()->start(), graph()->start())); | |
260 } | |
261 | |
262 | |
263 TARGET_TEST_P(ChangeLoweringCommonTest, Allocate) { | |
264 Node* p0 = Parameter(Type::Signed32()); | |
265 Node* alloc = graph()->NewNode(simplified()->Allocate(TENURED), p0, | |
266 graph()->start(), graph()->start()); | |
267 Reduction r = Reduce(alloc); | |
268 | |
269 // Only check that we lowered, but do not specify the exact form since | |
270 // this is subject to change. | |
271 ASSERT_TRUE(r.Changed()); | |
272 } | |
273 | |
274 } // namespace compiler | |
275 } // namespace internal | |
276 } // namespace v8 | |
OLD | NEW |