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