Line data Source code
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 <limits>
6 :
7 : #include "src/compiler/node-matchers.h"
8 : #include "src/compiler/representation-change.h"
9 : #include "src/compiler/type-cache.h"
10 : #include "src/objects-inl.h"
11 : #include "test/cctest/cctest.h"
12 : #include "test/cctest/compiler/codegen-tester.h"
13 : #include "test/cctest/compiler/graph-builder-tester.h"
14 : #include "test/cctest/compiler/value-helper.h"
15 :
16 : namespace v8 {
17 : namespace internal {
18 : namespace compiler {
19 :
20 530 : class RepresentationChangerTester : public HandleAndZoneScope,
21 : public GraphAndBuilders {
22 : public:
23 530 : explicit RepresentationChangerTester(int num_parameters = 0)
24 : : GraphAndBuilders(main_zone()),
25 : javascript_(main_zone()),
26 : jsgraph_(main_isolate(), main_graph_, &main_common_, &javascript_,
27 : &main_simplified_, &main_machine_),
28 1590 : changer_(&jsgraph_, main_isolate()) {
29 530 : Node* s = graph()->NewNode(common()->Start(num_parameters));
30 : graph()->SetStart(s);
31 530 : }
32 :
33 : JSOperatorBuilder javascript_;
34 : JSGraph jsgraph_;
35 : RepresentationChanger changer_;
36 :
37 : Isolate* isolate() { return main_isolate(); }
38 : Graph* graph() { return main_graph_; }
39 4630 : CommonOperatorBuilder* common() { return &main_common_; }
40 : JSGraph* jsgraph() { return &jsgraph_; }
41 140 : RepresentationChanger* changer() { return &changer_; }
42 :
43 : // TODO(titzer): use ValueChecker / ValueUtil
44 300 : void CheckInt32Constant(Node* n, int32_t expected) {
45 : Int32Matcher m(n);
46 300 : CHECK(m.HasValue());
47 300 : CHECK_EQ(expected, m.Value());
48 300 : }
49 :
50 290 : void CheckInt64Constant(Node* n, int64_t expected) {
51 : Int64Matcher m(n);
52 290 : CHECK(m.HasValue());
53 290 : CHECK_EQ(expected, m.Value());
54 290 : }
55 :
56 290 : void CheckUint32Constant(Node* n, uint32_t expected) {
57 : Uint32Matcher m(n);
58 290 : CHECK(m.HasValue());
59 290 : CHECK_EQ(static_cast<int>(expected), static_cast<int>(m.Value()));
60 290 : }
61 :
62 830 : void CheckFloat64Constant(Node* n, double expected) {
63 : Float64Matcher m(n);
64 830 : CHECK(m.HasValue());
65 830 : CHECK_DOUBLE_EQ(expected, m.Value());
66 830 : }
67 :
68 875 : void CheckFloat32Constant(Node* n, float expected) {
69 875 : CHECK_EQ(IrOpcode::kFloat32Constant, n->opcode());
70 875 : float fval = OpParameter<float>(n->op());
71 875 : CHECK_FLOAT_EQ(expected, fval);
72 875 : }
73 :
74 : void CheckHeapConstant(Node* n, HeapObject expected) {
75 : HeapObjectMatcher m(n);
76 : CHECK(m.HasValue());
77 : CHECK_EQ(expected, *m.Value());
78 : }
79 :
80 825 : void CheckNumberConstant(Node* n, double expected) {
81 : NumberMatcher m(n);
82 825 : CHECK_EQ(IrOpcode::kNumberConstant, n->opcode());
83 825 : CHECK(m.HasValue());
84 825 : CHECK_DOUBLE_EQ(expected, m.Value());
85 825 : }
86 :
87 610 : Node* Parameter(int index = 0) {
88 610 : Node* n = graph()->NewNode(common()->Parameter(index), graph()->start());
89 : NodeProperties::SetType(n, Type::Any());
90 610 : return n;
91 : }
92 :
93 4020 : Node* Return(Node* input) {
94 8040 : Node* n = graph()->NewNode(common()->Return(), jsgraph()->Int32Constant(0),
95 : input, graph()->start(), graph()->start());
96 4020 : return n;
97 : }
98 :
99 35 : void CheckTypeError(MachineRepresentation from, Type from_type,
100 : MachineRepresentation to) {
101 35 : changer()->testing_type_errors_ = true;
102 35 : changer()->type_error_ = false;
103 35 : Node* n = Parameter(0);
104 35 : Node* use = Return(n);
105 70 : Node* c = changer()->GetRepresentationFor(n, from, from_type, use,
106 35 : UseInfo(to, Truncation::None()));
107 35 : CHECK(changer()->type_error_);
108 35 : CHECK_EQ(n, c);
109 35 : }
110 :
111 105 : void CheckNop(MachineRepresentation from, Type from_type,
112 : MachineRepresentation to) {
113 105 : Node* n = Parameter(0);
114 105 : Node* use = Return(n);
115 210 : Node* c = changer()->GetRepresentationFor(n, from, from_type, use,
116 105 : UseInfo(to, Truncation::None()));
117 105 : CHECK_EQ(n, c);
118 105 : }
119 : };
120 :
121 : const MachineType kMachineTypes[] = {
122 : MachineType::Float32(), MachineType::Float64(),
123 : MachineType::Int8(), MachineType::Uint8(),
124 : MachineType::Int16(), MachineType::Uint16(),
125 : MachineType::Int32(), MachineType::Uint32(),
126 : MachineType::Int64(), MachineType::Uint64(),
127 : MachineType::AnyTagged(), MachineType::AnyCompressed()};
128 :
129 26644 : TEST(BoolToBit_constant) {
130 5 : RepresentationChangerTester r;
131 :
132 5 : Node* true_node = r.jsgraph()->TrueConstant();
133 5 : Node* true_use = r.Return(true_node);
134 10 : Node* true_bit = r.changer()->GetRepresentationFor(
135 : true_node, MachineRepresentation::kTagged, Type::None(), true_use,
136 5 : UseInfo(MachineRepresentation::kBit, Truncation::None()));
137 5 : r.CheckInt32Constant(true_bit, 1);
138 :
139 5 : Node* false_node = r.jsgraph()->FalseConstant();
140 5 : Node* false_use = r.Return(false_node);
141 10 : Node* false_bit = r.changer()->GetRepresentationFor(
142 : false_node, MachineRepresentation::kTagged, Type::None(), false_use,
143 5 : UseInfo(MachineRepresentation::kBit, Truncation::None()));
144 5 : r.CheckInt32Constant(false_bit, 0);
145 5 : }
146 :
147 26644 : TEST(ToTagged_constant) {
148 5 : RepresentationChangerTester r;
149 :
150 495 : for (double i : ValueHelper::float64_vector()) {
151 245 : Node* n = r.jsgraph()->Constant(i);
152 245 : Node* use = r.Return(n);
153 490 : Node* c = r.changer()->GetRepresentationFor(
154 : n, MachineRepresentation::kFloat64, Type::None(), use,
155 245 : UseInfo(MachineRepresentation::kTagged, Truncation::None()));
156 245 : r.CheckNumberConstant(c, i);
157 : }
158 :
159 585 : for (int i : ValueHelper::int32_vector()) {
160 290 : Node* n = r.jsgraph()->Constant(i);
161 290 : Node* use = r.Return(n);
162 580 : Node* c = r.changer()->GetRepresentationFor(
163 : n, MachineRepresentation::kWord32, Type::Signed32(), use,
164 290 : UseInfo(MachineRepresentation::kTagged, Truncation::None()));
165 290 : r.CheckNumberConstant(c, i);
166 : }
167 :
168 585 : for (uint32_t i : ValueHelper::uint32_vector()) {
169 290 : Node* n = r.jsgraph()->Constant(i);
170 290 : Node* use = r.Return(n);
171 580 : Node* c = r.changer()->GetRepresentationFor(
172 : n, MachineRepresentation::kWord32, Type::Unsigned32(), use,
173 290 : UseInfo(MachineRepresentation::kTagged, Truncation::None()));
174 290 : r.CheckNumberConstant(c, i);
175 : }
176 5 : }
177 :
178 26644 : TEST(ToFloat64_constant) {
179 5 : RepresentationChangerTester r;
180 :
181 495 : for (double i : ValueHelper::float64_vector()) {
182 245 : Node* n = r.jsgraph()->Constant(i);
183 245 : Node* use = r.Return(n);
184 490 : Node* c = r.changer()->GetRepresentationFor(
185 : n, MachineRepresentation::kTagged, Type::None(), use,
186 245 : UseInfo(MachineRepresentation::kFloat64, Truncation::None()));
187 245 : r.CheckFloat64Constant(c, i);
188 : }
189 :
190 585 : for (int i : ValueHelper::int32_vector()) {
191 290 : Node* n = r.jsgraph()->Constant(i);
192 290 : Node* use = r.Return(n);
193 580 : Node* c = r.changer()->GetRepresentationFor(
194 : n, MachineRepresentation::kWord32, Type::Signed32(), use,
195 290 : UseInfo(MachineRepresentation::kFloat64, Truncation::None()));
196 290 : r.CheckFloat64Constant(c, i);
197 : }
198 :
199 585 : for (uint32_t i : ValueHelper::uint32_vector()) {
200 290 : Node* n = r.jsgraph()->Constant(i);
201 290 : Node* use = r.Return(n);
202 580 : Node* c = r.changer()->GetRepresentationFor(
203 : n, MachineRepresentation::kWord32, Type::Unsigned32(), use,
204 290 : UseInfo(MachineRepresentation::kFloat64, Truncation::None()));
205 290 : r.CheckFloat64Constant(c, i);
206 : }
207 :
208 : {
209 5 : Node* n = r.jsgraph()->Constant(0);
210 5 : Node* use = r.Return(n);
211 15 : Node* c = r.changer()->GetRepresentationFor(
212 : n, MachineRepresentation::kWord64, Type::Range(0, 0, r.zone()), use,
213 5 : UseInfo(MachineRepresentation::kFloat64, Truncation::None()));
214 5 : r.CheckFloat64Constant(c, 0);
215 : }
216 5 : }
217 :
218 :
219 : static bool IsFloat32Int32(int32_t val) {
220 290 : return val >= -(1 << 23) && val <= (1 << 23);
221 : }
222 :
223 :
224 : static bool IsFloat32Uint32(uint32_t val) { return val <= (1 << 23); }
225 :
226 :
227 26644 : TEST(ToFloat32_constant) {
228 5 : RepresentationChangerTester r;
229 :
230 1155 : for (double i : ValueHelper::float32_vector()) {
231 575 : Node* n = r.jsgraph()->Constant(i);
232 575 : Node* use = r.Return(n);
233 1150 : Node* c = r.changer()->GetRepresentationFor(
234 : n, MachineRepresentation::kTagged, Type::None(), use,
235 575 : UseInfo(MachineRepresentation::kFloat32, Truncation::None()));
236 575 : r.CheckFloat32Constant(c, i);
237 : }
238 :
239 585 : for (int i : ValueHelper::int32_vector()) {
240 290 : if (!IsFloat32Int32(i)) continue;
241 155 : Node* n = r.jsgraph()->Constant(i);
242 155 : Node* use = r.Return(n);
243 310 : Node* c = r.changer()->GetRepresentationFor(
244 : n, MachineRepresentation::kWord32, Type::Signed32(), use,
245 155 : UseInfo(MachineRepresentation::kFloat32, Truncation::None()));
246 155 : r.CheckFloat32Constant(c, static_cast<float>(i));
247 : }
248 :
249 585 : for (uint32_t i : ValueHelper::uint32_vector()) {
250 290 : if (!IsFloat32Uint32(i)) continue;
251 145 : Node* n = r.jsgraph()->Constant(i);
252 145 : Node* use = r.Return(n);
253 290 : Node* c = r.changer()->GetRepresentationFor(
254 : n, MachineRepresentation::kWord32, Type::Unsigned32(), use,
255 145 : UseInfo(MachineRepresentation::kFloat32, Truncation::None()));
256 145 : r.CheckFloat32Constant(c, static_cast<float>(i));
257 : }
258 5 : }
259 :
260 26644 : TEST(ToInt32_constant) {
261 5 : RepresentationChangerTester r;
262 : {
263 585 : FOR_INT32_INPUTS(i) {
264 290 : Node* n = r.jsgraph()->Constant(i);
265 290 : Node* use = r.Return(n);
266 580 : Node* c = r.changer()->GetRepresentationFor(
267 : n, MachineRepresentation::kTagged, Type::Signed32(), use,
268 290 : UseInfo(MachineRepresentation::kWord32, Truncation::None()));
269 290 : r.CheckInt32Constant(c, i);
270 : }
271 : }
272 5 : }
273 :
274 26644 : TEST(ToUint32_constant) {
275 5 : RepresentationChangerTester r;
276 585 : FOR_UINT32_INPUTS(i) {
277 290 : Node* n = r.jsgraph()->Constant(static_cast<double>(i));
278 290 : Node* use = r.Return(n);
279 580 : Node* c = r.changer()->GetRepresentationFor(
280 : n, MachineRepresentation::kTagged, Type::Unsigned32(), use,
281 290 : UseInfo(MachineRepresentation::kWord32, Truncation::None()));
282 290 : r.CheckUint32Constant(c, i);
283 : }
284 5 : }
285 :
286 26644 : TEST(ToInt64_constant) {
287 5 : RepresentationChangerTester r;
288 585 : FOR_INT32_INPUTS(i) {
289 290 : Node* n = r.jsgraph()->Constant(i);
290 290 : Node* use = r.Return(n);
291 580 : Node* c = r.changer()->GetRepresentationFor(
292 290 : n, MachineRepresentation::kTagged, TypeCache::Get()->kSafeInteger, use,
293 290 : UseInfo(MachineRepresentation::kWord64, Truncation::None()));
294 290 : r.CheckInt64Constant(c, i);
295 : }
296 5 : }
297 :
298 300 : static void CheckChange(IrOpcode::Value expected, MachineRepresentation from,
299 : Type from_type, UseInfo use_info) {
300 300 : RepresentationChangerTester r;
301 :
302 300 : Node* n = r.Parameter();
303 300 : Node* use = r.Return(n);
304 : Node* c =
305 300 : r.changer()->GetRepresentationFor(n, from, from_type, use, use_info);
306 :
307 300 : CHECK_NE(c, n);
308 300 : CHECK_EQ(expected, c->opcode());
309 300 : CHECK_EQ(n, c->InputAt(0));
310 :
311 300 : if (expected == IrOpcode::kCheckedFloat64ToInt32 ||
312 : expected == IrOpcode::kCheckedFloat64ToInt64) {
313 : CheckForMinusZeroMode mode =
314 40 : from_type.Maybe(Type::MinusZero())
315 : ? use_info.minus_zero_check()
316 40 : : CheckForMinusZeroMode::kDontCheckForMinusZero;
317 40 : CHECK_EQ(mode, CheckMinusZeroParametersOf(c->op()).mode());
318 : }
319 300 : }
320 :
321 255 : static void CheckChange(IrOpcode::Value expected, MachineRepresentation from,
322 : Type from_type, MachineRepresentation to) {
323 510 : CheckChange(expected, from, from_type, UseInfo(to, Truncation::Any()));
324 255 : }
325 :
326 115 : static void CheckTwoChanges(IrOpcode::Value expected2,
327 : IrOpcode::Value expected1,
328 : MachineRepresentation from, Type from_type,
329 : MachineRepresentation to, UseInfo use_info) {
330 115 : RepresentationChangerTester r;
331 :
332 115 : Node* n = r.Parameter();
333 115 : Node* use = r.Return(n);
334 : Node* c1 =
335 115 : r.changer()->GetRepresentationFor(n, from, from_type, use, use_info);
336 :
337 115 : CHECK_NE(c1, n);
338 115 : CHECK_EQ(expected1, c1->opcode());
339 : Node* c2 = c1->InputAt(0);
340 115 : CHECK_NE(c2, n);
341 115 : CHECK_EQ(expected2, c2->opcode());
342 115 : CHECK_EQ(n, c2->InputAt(0));
343 115 : }
344 :
345 110 : static void CheckTwoChanges(IrOpcode::Value expected2,
346 : IrOpcode::Value expected1,
347 : MachineRepresentation from, Type from_type,
348 : MachineRepresentation to) {
349 220 : CheckTwoChanges(expected2, expected1, from, from_type, to,
350 110 : UseInfo(to, Truncation::None()));
351 110 : }
352 :
353 55 : static void CheckChange(IrOpcode::Value expected, MachineRepresentation from,
354 : Type from_type, MachineRepresentation to,
355 : UseInfo use_info) {
356 55 : RepresentationChangerTester r;
357 :
358 55 : Node* n = r.Parameter();
359 55 : Node* use = r.Return(n);
360 : Node* c =
361 55 : r.changer()->GetRepresentationFor(n, from, from_type, use, use_info);
362 :
363 55 : CHECK_NE(c, n);
364 55 : CHECK_EQ(expected, c->opcode());
365 55 : CHECK_EQ(n, c->InputAt(0));
366 55 : }
367 :
368 26644 : TEST(Word64) {
369 : CheckChange(IrOpcode::kChangeInt32ToInt64, MachineRepresentation::kWord8,
370 5 : TypeCache::Get()->kInt8, MachineRepresentation::kWord64);
371 : CheckChange(IrOpcode::kChangeUint32ToUint64, MachineRepresentation::kWord8,
372 5 : TypeCache::Get()->kUint8, MachineRepresentation::kWord64);
373 : CheckChange(IrOpcode::kChangeInt32ToInt64, MachineRepresentation::kWord16,
374 5 : TypeCache::Get()->kInt16, MachineRepresentation::kWord64);
375 : CheckChange(IrOpcode::kChangeUint32ToUint64, MachineRepresentation::kWord16,
376 5 : TypeCache::Get()->kUint16, MachineRepresentation::kWord64);
377 : CheckChange(IrOpcode::kChangeInt32ToInt64, MachineRepresentation::kWord32,
378 5 : Type::Signed32(), MachineRepresentation::kWord64);
379 : CheckChange(IrOpcode::kChangeUint32ToUint64, MachineRepresentation::kWord32,
380 5 : Type::Unsigned32(), MachineRepresentation::kWord64);
381 :
382 : CheckChange(IrOpcode::kTruncateInt64ToInt32, MachineRepresentation::kWord64,
383 5 : Type::Signed32(), MachineRepresentation::kWord32);
384 : CheckChange(IrOpcode::kTruncateInt64ToInt32, MachineRepresentation::kWord64,
385 5 : Type::Unsigned32(), MachineRepresentation::kWord32);
386 : CheckChange(IrOpcode::kTruncateInt64ToInt32, MachineRepresentation::kWord64,
387 5 : TypeCache::Get()->kSafeInteger, MachineRepresentation::kWord32,
388 5 : UseInfo::TruncatingWord32());
389 10 : CheckChange(
390 : IrOpcode::kCheckedInt64ToInt32, MachineRepresentation::kWord64,
391 5 : TypeCache::Get()->kSafeInteger, MachineRepresentation::kWord32,
392 5 : UseInfo::CheckedSigned32AsWord32(kIdentifyZeros, VectorSlotPair()));
393 10 : CheckChange(
394 : IrOpcode::kCheckedUint64ToInt32, MachineRepresentation::kWord64,
395 5 : TypeCache::Get()->kPositiveSafeInteger, MachineRepresentation::kWord32,
396 5 : UseInfo::CheckedSigned32AsWord32(kIdentifyZeros, VectorSlotPair()));
397 :
398 : CheckChange(IrOpcode::kChangeFloat64ToInt64, MachineRepresentation::kFloat64,
399 5 : Type::Signed32(), MachineRepresentation::kWord64);
400 : CheckChange(IrOpcode::kChangeFloat64ToInt64, MachineRepresentation::kFloat64,
401 5 : Type::Unsigned32(), MachineRepresentation::kWord64);
402 : CheckChange(IrOpcode::kChangeFloat64ToInt64, MachineRepresentation::kFloat64,
403 5 : TypeCache::Get()->kSafeInteger, MachineRepresentation::kWord64);
404 : CheckChange(IrOpcode::kChangeFloat64ToInt64, MachineRepresentation::kFloat64,
405 5 : TypeCache::Get()->kInt64, MachineRepresentation::kWord64);
406 : CheckChange(IrOpcode::kChangeFloat64ToUint64, MachineRepresentation::kFloat64,
407 5 : TypeCache::Get()->kUint64, MachineRepresentation::kWord64);
408 10 : CheckChange(
409 : IrOpcode::kCheckedFloat64ToInt64, MachineRepresentation::kFloat64,
410 : Type::Number(), MachineRepresentation::kWord64,
411 5 : UseInfo::CheckedSigned64AsWord64(kIdentifyZeros, VectorSlotPair()));
412 :
413 : CheckChange(IrOpcode::kChangeInt64ToFloat64, MachineRepresentation::kWord64,
414 5 : Type::Signed32(), MachineRepresentation::kFloat64);
415 : CheckChange(IrOpcode::kChangeInt64ToFloat64, MachineRepresentation::kWord64,
416 5 : Type::Unsigned32(), MachineRepresentation::kFloat64);
417 : CheckChange(IrOpcode::kChangeInt64ToFloat64, MachineRepresentation::kWord64,
418 5 : TypeCache::Get()->kSafeInteger, MachineRepresentation::kFloat64);
419 :
420 : CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
421 : IrOpcode::kChangeFloat64ToInt64,
422 : MachineRepresentation::kFloat32, Type::Signed32(),
423 5 : MachineRepresentation::kWord64);
424 : CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
425 : IrOpcode::kChangeFloat64ToInt64,
426 : MachineRepresentation::kFloat32, Type::Unsigned32(),
427 5 : MachineRepresentation::kWord64);
428 : CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
429 : IrOpcode::kChangeFloat64ToInt64,
430 5 : MachineRepresentation::kFloat32, TypeCache::Get()->kInt64,
431 5 : MachineRepresentation::kWord64);
432 : CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
433 : IrOpcode::kChangeFloat64ToUint64,
434 5 : MachineRepresentation::kFloat32, TypeCache::Get()->kUint64,
435 5 : MachineRepresentation::kWord64);
436 10 : CheckTwoChanges(
437 : IrOpcode::kChangeFloat32ToFloat64, IrOpcode::kCheckedFloat64ToInt64,
438 : MachineRepresentation::kFloat32, Type::Number(),
439 : MachineRepresentation::kWord64,
440 5 : UseInfo::CheckedSigned64AsWord64(kIdentifyZeros, VectorSlotPair()));
441 :
442 : CheckTwoChanges(IrOpcode::kChangeInt64ToFloat64,
443 : IrOpcode::kTruncateFloat64ToFloat32,
444 : MachineRepresentation::kWord64, Type::Signed32(),
445 5 : MachineRepresentation::kFloat32);
446 :
447 : CheckChange(IrOpcode::kChangeTaggedToInt64, MachineRepresentation::kTagged,
448 5 : Type::Signed32(), MachineRepresentation::kWord64);
449 : CheckChange(IrOpcode::kChangeTaggedToInt64, MachineRepresentation::kTagged,
450 5 : Type::Unsigned32(), MachineRepresentation::kWord64);
451 : CheckChange(IrOpcode::kChangeTaggedToInt64, MachineRepresentation::kTagged,
452 5 : TypeCache::Get()->kSafeInteger, MachineRepresentation::kWord64);
453 : CheckChange(IrOpcode::kChangeTaggedToInt64, MachineRepresentation::kTagged,
454 5 : TypeCache::Get()->kInt64, MachineRepresentation::kWord64);
455 : CheckChange(IrOpcode::kChangeTaggedSignedToInt64,
456 : MachineRepresentation::kTaggedSigned, Type::SignedSmall(),
457 5 : MachineRepresentation::kWord64);
458 10 : CheckChange(
459 : IrOpcode::kCheckedTaggedToInt64, MachineRepresentation::kTagged,
460 : Type::Number(), MachineRepresentation::kWord64,
461 5 : UseInfo::CheckedSigned64AsWord64(kIdentifyZeros, VectorSlotPair()));
462 10 : CheckChange(
463 : IrOpcode::kCheckedTaggedToInt64, MachineRepresentation::kTaggedPointer,
464 : Type::Number(), MachineRepresentation::kWord64,
465 5 : UseInfo::CheckedSigned64AsWord64(kIdentifyZeros, VectorSlotPair()));
466 :
467 : CheckTwoChanges(IrOpcode::kTruncateInt64ToInt32,
468 : IrOpcode::kChangeInt31ToTaggedSigned,
469 : MachineRepresentation::kWord64, Type::Signed31(),
470 5 : MachineRepresentation::kTagged);
471 : CheckTwoChanges(IrOpcode::kTruncateInt64ToInt32,
472 : IrOpcode::kChangeInt32ToTagged,
473 : MachineRepresentation::kWord64, Type::Signed32(),
474 5 : MachineRepresentation::kTagged);
475 : CheckTwoChanges(IrOpcode::kTruncateInt64ToInt32,
476 : IrOpcode::kChangeUint32ToTagged,
477 : MachineRepresentation::kWord64, Type::Unsigned32(),
478 5 : MachineRepresentation::kTagged);
479 : CheckChange(IrOpcode::kChangeInt64ToTagged, MachineRepresentation::kWord64,
480 5 : TypeCache::Get()->kSafeInteger, MachineRepresentation::kTagged);
481 : CheckChange(IrOpcode::kChangeUint64ToTagged, MachineRepresentation::kWord64,
482 5 : TypeCache::Get()->kPositiveSafeInteger,
483 5 : MachineRepresentation::kTagged);
484 :
485 : CheckTwoChanges(IrOpcode::kTruncateInt64ToInt32,
486 : IrOpcode::kChangeInt31ToTaggedSigned,
487 : MachineRepresentation::kWord64, Type::Signed31(),
488 5 : MachineRepresentation::kTaggedSigned);
489 : if (SmiValuesAre32Bits()) {
490 : CheckTwoChanges(IrOpcode::kTruncateInt64ToInt32,
491 : IrOpcode::kChangeInt32ToTagged,
492 : MachineRepresentation::kWord64, Type::Signed32(),
493 5 : MachineRepresentation::kTaggedSigned);
494 : }
495 10 : CheckChange(IrOpcode::kCheckedInt64ToTaggedSigned,
496 5 : MachineRepresentation::kWord64, TypeCache::Get()->kSafeInteger,
497 : MachineRepresentation::kTaggedSigned,
498 5 : UseInfo::CheckedSignedSmallAsTaggedSigned(VectorSlotPair()));
499 10 : CheckChange(IrOpcode::kCheckedUint64ToTaggedSigned,
500 : MachineRepresentation::kWord64,
501 5 : TypeCache::Get()->kPositiveSafeInteger,
502 : MachineRepresentation::kTaggedSigned,
503 5 : UseInfo::CheckedSignedSmallAsTaggedSigned(VectorSlotPair()));
504 :
505 : CheckTwoChanges(
506 : IrOpcode::kChangeInt64ToFloat64, IrOpcode::kChangeFloat64ToTaggedPointer,
507 5 : MachineRepresentation::kWord64, TypeCache::Get()->kSafeInteger,
508 5 : MachineRepresentation::kTaggedPointer);
509 5 : }
510 :
511 26644 : TEST(SingleChanges) {
512 : CheckChange(IrOpcode::kChangeTaggedToBit, MachineRepresentation::kTagged,
513 5 : Type::Boolean(), MachineRepresentation::kBit);
514 : CheckChange(IrOpcode::kChangeBitToTagged, MachineRepresentation::kBit,
515 5 : Type::Boolean(), MachineRepresentation::kTagged);
516 :
517 : CheckChange(IrOpcode::kChangeInt31ToTaggedSigned,
518 : MachineRepresentation::kWord32, Type::Signed31(),
519 5 : MachineRepresentation::kTagged);
520 : CheckChange(IrOpcode::kChangeInt32ToTagged, MachineRepresentation::kWord32,
521 5 : Type::Signed32(), MachineRepresentation::kTagged);
522 : CheckChange(IrOpcode::kChangeUint32ToTagged, MachineRepresentation::kWord32,
523 5 : Type::Unsigned32(), MachineRepresentation::kTagged);
524 : CheckChange(IrOpcode::kChangeFloat64ToTagged, MachineRepresentation::kFloat64,
525 5 : Type::Number(), MachineRepresentation::kTagged);
526 : CheckTwoChanges(IrOpcode::kChangeFloat64ToInt32,
527 : IrOpcode::kChangeInt31ToTaggedSigned,
528 : MachineRepresentation::kFloat64, Type::Signed31(),
529 5 : MachineRepresentation::kTagged);
530 : CheckTwoChanges(IrOpcode::kChangeFloat64ToInt32,
531 : IrOpcode::kChangeInt32ToTagged,
532 : MachineRepresentation::kFloat64, Type::Signed32(),
533 5 : MachineRepresentation::kTagged);
534 : CheckTwoChanges(IrOpcode::kChangeFloat64ToUint32,
535 : IrOpcode::kChangeUint32ToTagged,
536 : MachineRepresentation::kFloat64, Type::Unsigned32(),
537 5 : MachineRepresentation::kTagged);
538 :
539 : CheckChange(IrOpcode::kChangeTaggedToInt32, MachineRepresentation::kTagged,
540 5 : Type::Signed32(), MachineRepresentation::kWord32);
541 : CheckChange(IrOpcode::kChangeTaggedToUint32, MachineRepresentation::kTagged,
542 5 : Type::Unsigned32(), MachineRepresentation::kWord32);
543 : CheckChange(IrOpcode::kChangeTaggedToFloat64, MachineRepresentation::kTagged,
544 5 : Type::Number(), MachineRepresentation::kFloat64);
545 : CheckChange(IrOpcode::kTruncateTaggedToFloat64,
546 : MachineRepresentation::kTagged, Type::NumberOrUndefined(),
547 5 : MachineRepresentation::kFloat64);
548 : CheckChange(IrOpcode::kChangeTaggedToFloat64, MachineRepresentation::kTagged,
549 5 : Type::Signed31(), MachineRepresentation::kFloat64);
550 :
551 : // Int32,Uint32 <-> Float64 are actually machine conversions.
552 : CheckChange(IrOpcode::kChangeInt32ToFloat64, MachineRepresentation::kWord32,
553 5 : Type::Signed32(), MachineRepresentation::kFloat64);
554 10 : CheckChange(IrOpcode::kChangeInt32ToFloat64, MachineRepresentation::kWord32,
555 : Type::Signed32OrMinusZero(), MachineRepresentation::kFloat64,
556 : UseInfo(MachineRepresentation::kFloat64,
557 5 : Truncation::Any(kIdentifyZeros)));
558 : CheckChange(IrOpcode::kChangeUint32ToFloat64, MachineRepresentation::kWord32,
559 5 : Type::Unsigned32(), MachineRepresentation::kFloat64);
560 : CheckChange(IrOpcode::kChangeFloat64ToInt32, MachineRepresentation::kFloat64,
561 5 : Type::Signed32(), MachineRepresentation::kWord32);
562 : CheckChange(IrOpcode::kChangeFloat64ToUint32, MachineRepresentation::kFloat64,
563 5 : Type::Unsigned32(), MachineRepresentation::kWord32);
564 :
565 : CheckChange(IrOpcode::kTruncateFloat64ToFloat32,
566 : MachineRepresentation::kFloat64, Type::Number(),
567 5 : MachineRepresentation::kFloat32);
568 :
569 : // Int32,Uint32 <-> Float32 require two changes.
570 : CheckTwoChanges(IrOpcode::kChangeInt32ToFloat64,
571 : IrOpcode::kTruncateFloat64ToFloat32,
572 : MachineRepresentation::kWord32, Type::Signed32(),
573 5 : MachineRepresentation::kFloat32);
574 : CheckTwoChanges(IrOpcode::kChangeUint32ToFloat64,
575 : IrOpcode::kTruncateFloat64ToFloat32,
576 : MachineRepresentation::kWord32, Type::Unsigned32(),
577 5 : MachineRepresentation::kFloat32);
578 : CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
579 : IrOpcode::kChangeFloat64ToInt32,
580 : MachineRepresentation::kFloat32, Type::Signed32(),
581 5 : MachineRepresentation::kWord32);
582 : CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
583 : IrOpcode::kChangeFloat64ToUint32,
584 : MachineRepresentation::kFloat32, Type::Unsigned32(),
585 5 : MachineRepresentation::kWord32);
586 :
587 : // Float32 <-> Tagged require two changes.
588 : CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
589 : IrOpcode::kChangeFloat64ToTagged,
590 : MachineRepresentation::kFloat32, Type::Number(),
591 5 : MachineRepresentation::kTagged);
592 : CheckTwoChanges(IrOpcode::kChangeTaggedToFloat64,
593 : IrOpcode::kTruncateFloat64ToFloat32,
594 : MachineRepresentation::kTagged, Type::Number(),
595 5 : MachineRepresentation::kFloat32);
596 5 : }
597 :
598 :
599 26644 : TEST(SignednessInWord32) {
600 5 : RepresentationChangerTester r;
601 :
602 : CheckChange(IrOpcode::kChangeTaggedToInt32, MachineRepresentation::kTagged,
603 5 : Type::Signed32(), MachineRepresentation::kWord32);
604 : CheckChange(IrOpcode::kChangeTaggedToUint32, MachineRepresentation::kTagged,
605 5 : Type::Unsigned32(), MachineRepresentation::kWord32);
606 : CheckChange(IrOpcode::kChangeInt32ToFloat64, MachineRepresentation::kWord32,
607 5 : Type::Signed32(), MachineRepresentation::kFloat64);
608 : CheckChange(IrOpcode::kChangeFloat64ToInt32, MachineRepresentation::kFloat64,
609 5 : Type::Signed32(), MachineRepresentation::kWord32);
610 10 : CheckChange(IrOpcode::kTruncateFloat64ToWord32,
611 : MachineRepresentation::kFloat64, Type::Number(),
612 : MachineRepresentation::kWord32,
613 5 : UseInfo(MachineRepresentation::kWord32, Truncation::Word32()));
614 10 : CheckChange(IrOpcode::kCheckedTruncateTaggedToWord32,
615 : MachineRepresentation::kTagged, Type::NonInternal(),
616 : MachineRepresentation::kWord32,
617 5 : UseInfo::CheckedNumberOrOddballAsWord32(VectorSlotPair()));
618 :
619 : CheckTwoChanges(IrOpcode::kChangeInt32ToFloat64,
620 : IrOpcode::kTruncateFloat64ToFloat32,
621 : MachineRepresentation::kWord32, Type::Signed32(),
622 5 : MachineRepresentation::kFloat32);
623 : CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
624 : IrOpcode::kTruncateFloat64ToWord32,
625 : MachineRepresentation::kFloat32, Type::Number(),
626 5 : MachineRepresentation::kWord32);
627 :
628 10 : CheckChange(
629 : IrOpcode::kCheckedUint32ToInt32, MachineRepresentation::kWord32,
630 : Type::Unsigned32(),
631 5 : UseInfo::CheckedSigned32AsWord32(kIdentifyZeros, VectorSlotPair()));
632 5 : }
633 :
634 26644 : TEST(CompressedAndTagged) {
635 : // Simple Tagged to Compressed
636 : CheckChange(IrOpcode::kChangeTaggedToCompressed,
637 : MachineRepresentation::kTagged, Type::Any(),
638 5 : MachineRepresentation::kCompressed);
639 : CheckChange(IrOpcode::kChangeTaggedPointerToCompressedPointer,
640 : MachineRepresentation::kTaggedPointer, Type::Any(),
641 5 : MachineRepresentation::kCompressedPointer);
642 : CheckChange(IrOpcode::kChangeTaggedSignedToCompressedSigned,
643 : MachineRepresentation::kTaggedSigned, Type::Any(),
644 5 : MachineRepresentation::kCompressedSigned);
645 :
646 : // Simple Compressed to Tagged
647 : CheckChange(IrOpcode::kChangeCompressedToTagged,
648 : MachineRepresentation::kCompressed, Type::Any(),
649 5 : MachineRepresentation::kTagged);
650 : CheckChange(IrOpcode::kChangeCompressedPointerToTaggedPointer,
651 : MachineRepresentation::kCompressedPointer, Type::Any(),
652 5 : MachineRepresentation::kTaggedPointer);
653 : CheckChange(IrOpcode::kChangeCompressedSignedToTaggedSigned,
654 : MachineRepresentation::kCompressedSigned, Type::Any(),
655 5 : MachineRepresentation::kTaggedSigned);
656 :
657 : // Compressed To TaggedSigned
658 : CheckChange(IrOpcode::kChangeCompressedToTaggedSigned,
659 : MachineRepresentation::kCompressed, Type::SignedSmall(),
660 5 : MachineRepresentation::kTaggedSigned);
661 :
662 : // Tagged To CompressedSigned
663 : CheckChange(IrOpcode::kChangeTaggedToCompressedSigned,
664 : MachineRepresentation::kTagged, Type::SignedSmall(),
665 5 : MachineRepresentation::kCompressedSigned);
666 5 : }
667 :
668 10 : static void TestMinusZeroCheck(IrOpcode::Value expected, Type from_type) {
669 10 : RepresentationChangerTester r;
670 :
671 20 : CheckChange(
672 : expected, MachineRepresentation::kFloat64, from_type,
673 10 : UseInfo::CheckedSignedSmallAsWord32(kDistinguishZeros, VectorSlotPair()));
674 :
675 20 : CheckChange(
676 : expected, MachineRepresentation::kFloat64, from_type,
677 10 : UseInfo::CheckedSignedSmallAsWord32(kIdentifyZeros, VectorSlotPair()));
678 :
679 20 : CheckChange(
680 : expected, MachineRepresentation::kFloat64, from_type,
681 10 : UseInfo::CheckedSigned32AsWord32(kDistinguishZeros, VectorSlotPair()));
682 :
683 20 : CheckChange(
684 : expected, MachineRepresentation::kFloat64, from_type,
685 10 : UseInfo::CheckedSigned32AsWord32(kDistinguishZeros, VectorSlotPair()));
686 10 : }
687 :
688 26644 : TEST(MinusZeroCheck) {
689 5 : TestMinusZeroCheck(IrOpcode::kCheckedFloat64ToInt32, Type::NumberOrOddball());
690 : // PlainNumber cannot be minus zero so the minus zero check should be
691 : // eliminated.
692 5 : TestMinusZeroCheck(IrOpcode::kCheckedFloat64ToInt32, Type::PlainNumber());
693 5 : }
694 :
695 26644 : TEST(Nops) {
696 5 : RepresentationChangerTester r;
697 :
698 : // X -> X is always a nop for any single representation X.
699 125 : for (size_t i = 0; i < arraysize(kMachineTypes); i++) {
700 60 : r.CheckNop(kMachineTypes[i].representation(), Type::Number(),
701 60 : kMachineTypes[i].representation());
702 : }
703 :
704 : // 32-bit floats.
705 : r.CheckNop(MachineRepresentation::kFloat32, Type::Number(),
706 5 : MachineRepresentation::kFloat32);
707 :
708 : // 32-bit words can be used as smaller word sizes and vice versa, because
709 : // loads from memory implicitly sign or zero extend the value to the
710 : // full machine word size, and stores implicitly truncate.
711 : r.CheckNop(MachineRepresentation::kWord32, Type::Signed32(),
712 5 : MachineRepresentation::kWord8);
713 : r.CheckNop(MachineRepresentation::kWord32, Type::Signed32(),
714 5 : MachineRepresentation::kWord16);
715 : r.CheckNop(MachineRepresentation::kWord32, Type::Signed32(),
716 5 : MachineRepresentation::kWord32);
717 : r.CheckNop(MachineRepresentation::kWord8, Type::Signed32(),
718 5 : MachineRepresentation::kWord32);
719 : r.CheckNop(MachineRepresentation::kWord16, Type::Signed32(),
720 5 : MachineRepresentation::kWord32);
721 :
722 : // kRepBit (result of comparison) is implicitly a wordish thing.
723 : r.CheckNop(MachineRepresentation::kBit, Type::Boolean(),
724 5 : MachineRepresentation::kWord8);
725 : r.CheckNop(MachineRepresentation::kBit, Type::Boolean(),
726 5 : MachineRepresentation::kWord16);
727 : r.CheckNop(MachineRepresentation::kBit, Type::Boolean(),
728 5 : MachineRepresentation::kWord32);
729 5 : }
730 :
731 :
732 26644 : TEST(TypeErrors) {
733 5 : RepresentationChangerTester r;
734 :
735 : // Floats cannot be implicitly converted to/from comparison conditions.
736 : r.CheckTypeError(MachineRepresentation::kBit, Type::Number(),
737 5 : MachineRepresentation::kFloat32);
738 : r.CheckTypeError(MachineRepresentation::kBit, Type::Boolean(),
739 5 : MachineRepresentation::kFloat32);
740 :
741 : // Word64 is internal and shouldn't be implicitly converted.
742 : r.CheckTypeError(MachineRepresentation::kWord64, Type::Internal(),
743 5 : MachineRepresentation::kTagged);
744 : r.CheckTypeError(MachineRepresentation::kTagged, Type::Number(),
745 5 : MachineRepresentation::kWord64);
746 : r.CheckTypeError(MachineRepresentation::kTagged, Type::Boolean(),
747 5 : MachineRepresentation::kWord64);
748 : r.CheckTypeError(MachineRepresentation::kWord64, Type::Internal(),
749 5 : MachineRepresentation::kWord32);
750 : r.CheckTypeError(MachineRepresentation::kWord32, Type::Number(),
751 5 : MachineRepresentation::kWord64);
752 5 : }
753 :
754 : } // namespace compiler
755 : } // namespace internal
756 79917 : } // namespace v8
|