• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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