• 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 "src/compiler/common-operator.h"
8 #include "src/compiler/opcodes.h"
9 #include "src/compiler/operator.h"
10 #include "src/compiler/operator-properties.h"
11 #include "test/unittests/test-utils.h"
12 
13 namespace v8 {
14 namespace internal {
15 namespace compiler {
16 
17 
18 // -----------------------------------------------------------------------------
19 // Shared operators.
20 
21 
22 namespace {
23 
24 struct SharedOperator {
25   const Operator* (CommonOperatorBuilder::*constructor)();
26   IrOpcode::Value opcode;
27   Operator::Properties properties;
28   int value_input_count;
29   int effect_input_count;
30   int control_input_count;
31   int value_output_count;
32   int effect_output_count;
33   int control_output_count;
34 };
35 
36 
operator <<(std::ostream & os,const SharedOperator & fop)37 std::ostream& operator<<(std::ostream& os, const SharedOperator& fop) {
38   return os << IrOpcode::Mnemonic(fop.opcode);
39 }
40 
41 
42 const SharedOperator kSharedOperators[] = {
43 #define SHARED(Name, properties, value_input_count, effect_input_count,      \
44                control_input_count, value_output_count, effect_output_count, \
45                control_output_count)                                         \
46   {                                                                          \
47     &CommonOperatorBuilder::Name, IrOpcode::k##Name, properties,             \
48         value_input_count, effect_input_count, control_input_count,          \
49         value_output_count, effect_output_count, control_output_count        \
50   }
51     SHARED(Dead, Operator::kFoldable, 0, 0, 0, 1, 1, 1),
52     SHARED(IfTrue, Operator::kKontrol, 0, 0, 1, 0, 0, 1),
53     SHARED(IfFalse, Operator::kKontrol, 0, 0, 1, 0, 0, 1),
54     SHARED(IfSuccess, Operator::kKontrol, 0, 0, 1, 0, 0, 1),
55     SHARED(Throw, Operator::kKontrol, 1, 1, 1, 0, 0, 1),
56     SHARED(Terminate, Operator::kKontrol, 0, 1, 1, 0, 0, 1)
57 #undef SHARED
58 };
59 
60 
61 class CommonSharedOperatorTest
62     : public TestWithZone,
63       public ::testing::WithParamInterface<SharedOperator> {};
64 
65 }  // namespace
66 
67 
TEST_P(CommonSharedOperatorTest,InstancesAreGloballyShared)68 TEST_P(CommonSharedOperatorTest, InstancesAreGloballyShared) {
69   const SharedOperator& sop = GetParam();
70   CommonOperatorBuilder common1(zone());
71   CommonOperatorBuilder common2(zone());
72   EXPECT_EQ((common1.*sop.constructor)(), (common2.*sop.constructor)());
73 }
74 
75 
TEST_P(CommonSharedOperatorTest,NumberOfInputsAndOutputs)76 TEST_P(CommonSharedOperatorTest, NumberOfInputsAndOutputs) {
77   CommonOperatorBuilder common(zone());
78   const SharedOperator& sop = GetParam();
79   const Operator* op = (common.*sop.constructor)();
80 
81   EXPECT_EQ(sop.value_input_count, op->ValueInputCount());
82   EXPECT_EQ(sop.effect_input_count, op->EffectInputCount());
83   EXPECT_EQ(sop.control_input_count, op->ControlInputCount());
84   EXPECT_EQ(
85       sop.value_input_count + sop.effect_input_count + sop.control_input_count,
86       OperatorProperties::GetTotalInputCount(op));
87 
88   EXPECT_EQ(sop.value_output_count, op->ValueOutputCount());
89   EXPECT_EQ(sop.effect_output_count, op->EffectOutputCount());
90   EXPECT_EQ(sop.control_output_count, op->ControlOutputCount());
91 }
92 
93 
TEST_P(CommonSharedOperatorTest,OpcodeIsCorrect)94 TEST_P(CommonSharedOperatorTest, OpcodeIsCorrect) {
95   CommonOperatorBuilder common(zone());
96   const SharedOperator& sop = GetParam();
97   const Operator* op = (common.*sop.constructor)();
98   EXPECT_EQ(sop.opcode, op->opcode());
99 }
100 
101 
TEST_P(CommonSharedOperatorTest,Properties)102 TEST_P(CommonSharedOperatorTest, Properties) {
103   CommonOperatorBuilder common(zone());
104   const SharedOperator& sop = GetParam();
105   const Operator* op = (common.*sop.constructor)();
106   EXPECT_EQ(sop.properties, op->properties());
107 }
108 
109 
110 INSTANTIATE_TEST_CASE_P(CommonOperatorTest, CommonSharedOperatorTest,
111                         ::testing::ValuesIn(kSharedOperators));
112 
113 
114 // -----------------------------------------------------------------------------
115 // Other operators.
116 
117 
118 namespace {
119 
120 class CommonOperatorTest : public TestWithZone {
121  public:
CommonOperatorTest()122   CommonOperatorTest() : common_(zone()) {}
~CommonOperatorTest()123   ~CommonOperatorTest() override {}
124 
common()125   CommonOperatorBuilder* common() { return &common_; }
126 
127  private:
128   CommonOperatorBuilder common_;
129 };
130 
131 
132 const int kArguments[] = {1, 5, 6, 42, 100, 10000, 65000};
133 
134 
135 const size_t kCases[] = {3, 4, 100, 255, 1024, 65000};
136 
137 
138 const float kFloatValues[] = {-std::numeric_limits<float>::infinity(),
139                               std::numeric_limits<float>::min(),
140                               -1.0f,
141                               -0.0f,
142                               0.0f,
143                               1.0f,
144                               std::numeric_limits<float>::max(),
145                               std::numeric_limits<float>::infinity(),
146                               std::numeric_limits<float>::quiet_NaN(),
147                               std::numeric_limits<float>::signaling_NaN()};
148 
149 
150 const size_t kInputCounts[] = {3, 4, 100, 255, 1024, 65000};
151 
152 
153 const int32_t kInt32Values[] = {
154     std::numeric_limits<int32_t>::min(), -1914954528, -1698749618, -1578693386,
155     -1577976073, -1573998034, -1529085059, -1499540537, -1299205097,
156     -1090814845, -938186388, -806828902, -750927650, -520676892, -513661538,
157     -453036354, -433622833, -282638793, -28375, -27788, -22770, -18806, -14173,
158     -11956, -11200, -10212, -8160, -3751, -2758, -1522, -121, -120, -118, -117,
159     -106, -84, -80, -74, -59, -52, -48, -39, -35, -17, -11, -10, -9, -7, -5, 0,
160     9, 12, 17, 23, 29, 31, 33, 35, 40, 47, 55, 56, 62, 64, 67, 68, 69, 74, 79,
161     84, 89, 90, 97, 104, 118, 124, 126, 127, 7278, 17787, 24136, 24202, 25570,
162     26680, 30242, 32399, 420886487, 642166225, 821912648, 822577803, 851385718,
163     1212241078, 1411419304, 1589626102, 1596437184, 1876245816, 1954730266,
164     2008792749, 2045320228, std::numeric_limits<int32_t>::max()};
165 
166 
167 const BranchHint kBranchHints[] = {BranchHint::kNone, BranchHint::kTrue,
168                                    BranchHint::kFalse};
169 
170 }  // namespace
171 
172 
TEST_F(CommonOperatorTest,End)173 TEST_F(CommonOperatorTest, End) {
174   TRACED_FOREACH(size_t, input_count, kInputCounts) {
175     const Operator* const op = common()->End(input_count);
176     EXPECT_EQ(IrOpcode::kEnd, op->opcode());
177     EXPECT_EQ(Operator::kKontrol, op->properties());
178     EXPECT_EQ(0, op->ValueInputCount());
179     EXPECT_EQ(0, op->EffectInputCount());
180     EXPECT_EQ(input_count, static_cast<uint32_t>(op->ControlInputCount()));
181     EXPECT_EQ(input_count, static_cast<uint32_t>(
182                                OperatorProperties::GetTotalInputCount(op)));
183     EXPECT_EQ(0, op->ValueOutputCount());
184     EXPECT_EQ(0, op->EffectOutputCount());
185     EXPECT_EQ(0, op->ControlOutputCount());
186   }
187 }
188 
189 
TEST_F(CommonOperatorTest,Return)190 TEST_F(CommonOperatorTest, Return) {
191   TRACED_FOREACH(int, input_count, kArguments) {
192     const Operator* const op = common()->Return(input_count);
193     EXPECT_EQ(IrOpcode::kReturn, op->opcode());
194     EXPECT_EQ(Operator::kNoThrow, op->properties());
195     EXPECT_EQ(input_count, op->ValueInputCount());
196     EXPECT_EQ(1, op->EffectInputCount());
197     EXPECT_EQ(1, op->ControlInputCount());
198     EXPECT_EQ(2 + input_count, OperatorProperties::GetTotalInputCount(op));
199     EXPECT_EQ(0, op->ValueOutputCount());
200     EXPECT_EQ(0, op->EffectOutputCount());
201     EXPECT_EQ(1, op->ControlOutputCount());
202   }
203 }
204 
205 
TEST_F(CommonOperatorTest,Branch)206 TEST_F(CommonOperatorTest, Branch) {
207   TRACED_FOREACH(BranchHint, hint, kBranchHints) {
208     const Operator* const op = common()->Branch(hint);
209     EXPECT_EQ(IrOpcode::kBranch, op->opcode());
210     EXPECT_EQ(Operator::kKontrol, op->properties());
211     EXPECT_EQ(hint, BranchHintOf(op));
212     EXPECT_EQ(1, op->ValueInputCount());
213     EXPECT_EQ(0, op->EffectInputCount());
214     EXPECT_EQ(1, op->ControlInputCount());
215     EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op));
216     EXPECT_EQ(0, op->ValueOutputCount());
217     EXPECT_EQ(0, op->EffectOutputCount());
218     EXPECT_EQ(2, op->ControlOutputCount());
219   }
220 }
221 
222 
TEST_F(CommonOperatorTest,IfException)223 TEST_F(CommonOperatorTest, IfException) {
224   static const IfExceptionHint kIfExceptionHints[] = {
225       IfExceptionHint::kLocallyCaught, IfExceptionHint::kLocallyUncaught};
226   TRACED_FOREACH(IfExceptionHint, hint, kIfExceptionHints) {
227     const Operator* const op = common()->IfException(hint);
228     EXPECT_EQ(IrOpcode::kIfException, op->opcode());
229     EXPECT_EQ(Operator::kKontrol, op->properties());
230     EXPECT_EQ(0, op->ValueInputCount());
231     EXPECT_EQ(1, op->EffectInputCount());
232     EXPECT_EQ(1, op->ControlInputCount());
233     EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op));
234     EXPECT_EQ(1, op->ValueOutputCount());
235     EXPECT_EQ(1, op->EffectOutputCount());
236     EXPECT_EQ(1, op->ControlOutputCount());
237   }
238 }
239 
240 
TEST_F(CommonOperatorTest,Switch)241 TEST_F(CommonOperatorTest, Switch) {
242   TRACED_FOREACH(size_t, cases, kCases) {
243     const Operator* const op = common()->Switch(cases);
244     EXPECT_EQ(IrOpcode::kSwitch, op->opcode());
245     EXPECT_EQ(Operator::kKontrol, op->properties());
246     EXPECT_EQ(1, op->ValueInputCount());
247     EXPECT_EQ(0, op->EffectInputCount());
248     EXPECT_EQ(1, op->ControlInputCount());
249     EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op));
250     EXPECT_EQ(0, op->ValueOutputCount());
251     EXPECT_EQ(0, op->EffectOutputCount());
252     EXPECT_EQ(static_cast<int>(cases), op->ControlOutputCount());
253   }
254 }
255 
256 
TEST_F(CommonOperatorTest,IfValue)257 TEST_F(CommonOperatorTest, IfValue) {
258   TRACED_FOREACH(int32_t, value, kInt32Values) {
259     const Operator* const op = common()->IfValue(value);
260     EXPECT_EQ(IrOpcode::kIfValue, op->opcode());
261     EXPECT_EQ(Operator::kKontrol, op->properties());
262     EXPECT_EQ(value, OpParameter<int32_t>(op));
263     EXPECT_EQ(0, op->ValueInputCount());
264     EXPECT_EQ(0, op->EffectInputCount());
265     EXPECT_EQ(1, op->ControlInputCount());
266     EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op));
267     EXPECT_EQ(0, op->ValueOutputCount());
268     EXPECT_EQ(0, op->EffectOutputCount());
269     EXPECT_EQ(1, op->ControlOutputCount());
270   }
271 }
272 
273 
TEST_F(CommonOperatorTest,Select)274 TEST_F(CommonOperatorTest, Select) {
275   static const MachineRepresentation kMachineRepresentations[] = {
276       MachineRepresentation::kBit,     MachineRepresentation::kWord8,
277       MachineRepresentation::kWord16,  MachineRepresentation::kWord32,
278       MachineRepresentation::kWord64,  MachineRepresentation::kFloat32,
279       MachineRepresentation::kFloat64, MachineRepresentation::kTagged};
280 
281 
282   TRACED_FOREACH(MachineRepresentation, rep, kMachineRepresentations) {
283     TRACED_FOREACH(BranchHint, hint, kBranchHints) {
284       const Operator* const op = common()->Select(rep, hint);
285       EXPECT_EQ(IrOpcode::kSelect, op->opcode());
286       EXPECT_EQ(Operator::kPure, op->properties());
287       EXPECT_EQ(rep, SelectParametersOf(op).representation());
288       EXPECT_EQ(hint, SelectParametersOf(op).hint());
289       EXPECT_EQ(3, op->ValueInputCount());
290       EXPECT_EQ(0, op->EffectInputCount());
291       EXPECT_EQ(0, op->ControlInputCount());
292       EXPECT_EQ(3, OperatorProperties::GetTotalInputCount(op));
293       EXPECT_EQ(1, op->ValueOutputCount());
294       EXPECT_EQ(0, op->EffectOutputCount());
295       EXPECT_EQ(0, op->ControlOutputCount());
296     }
297   }
298 }
299 
300 
TEST_F(CommonOperatorTest,Float32Constant)301 TEST_F(CommonOperatorTest, Float32Constant) {
302   TRACED_FOREACH(float, value, kFloatValues) {
303     const Operator* op = common()->Float32Constant(value);
304     EXPECT_PRED2(base::bit_equal_to<float>(), value, OpParameter<float>(op));
305     EXPECT_EQ(0, op->ValueInputCount());
306     EXPECT_EQ(0, OperatorProperties::GetTotalInputCount(op));
307     EXPECT_EQ(0, op->ControlOutputCount());
308     EXPECT_EQ(0, op->EffectOutputCount());
309     EXPECT_EQ(1, op->ValueOutputCount());
310   }
311   TRACED_FOREACH(float, v1, kFloatValues) {
312     TRACED_FOREACH(float, v2, kFloatValues) {
313       const Operator* op1 = common()->Float32Constant(v1);
314       const Operator* op2 = common()->Float32Constant(v2);
315       EXPECT_EQ(bit_cast<uint32_t>(v1) == bit_cast<uint32_t>(v2),
316                 op1->Equals(op2));
317     }
318   }
319 }
320 
321 
TEST_F(CommonOperatorTest,Float64Constant)322 TEST_F(CommonOperatorTest, Float64Constant) {
323   TRACED_FOREACH(double, value, kFloatValues) {
324     const Operator* op = common()->Float64Constant(value);
325     EXPECT_PRED2(base::bit_equal_to<double>(), value, OpParameter<double>(op));
326     EXPECT_EQ(0, op->ValueInputCount());
327     EXPECT_EQ(0, OperatorProperties::GetTotalInputCount(op));
328     EXPECT_EQ(0, op->ControlOutputCount());
329     EXPECT_EQ(0, op->EffectOutputCount());
330     EXPECT_EQ(1, op->ValueOutputCount());
331   }
332   TRACED_FOREACH(double, v1, kFloatValues) {
333     TRACED_FOREACH(double, v2, kFloatValues) {
334       const Operator* op1 = common()->Float64Constant(v1);
335       const Operator* op2 = common()->Float64Constant(v2);
336       EXPECT_EQ(bit_cast<uint64_t>(v1) == bit_cast<uint64_t>(v2),
337                 op1->Equals(op2));
338     }
339   }
340 }
341 
342 
TEST_F(CommonOperatorTest,NumberConstant)343 TEST_F(CommonOperatorTest, NumberConstant) {
344   TRACED_FOREACH(double, value, kFloatValues) {
345     const Operator* op = common()->NumberConstant(value);
346     EXPECT_PRED2(base::bit_equal_to<double>(), value, OpParameter<double>(op));
347     EXPECT_EQ(0, op->ValueInputCount());
348     EXPECT_EQ(0, OperatorProperties::GetTotalInputCount(op));
349     EXPECT_EQ(0, op->ControlOutputCount());
350     EXPECT_EQ(0, op->EffectOutputCount());
351     EXPECT_EQ(1, op->ValueOutputCount());
352   }
353   TRACED_FOREACH(double, v1, kFloatValues) {
354     TRACED_FOREACH(double, v2, kFloatValues) {
355       const Operator* op1 = common()->NumberConstant(v1);
356       const Operator* op2 = common()->NumberConstant(v2);
357       EXPECT_EQ(bit_cast<uint64_t>(v1) == bit_cast<uint64_t>(v2),
358                 op1->Equals(op2));
359     }
360   }
361 }
362 
363 
TEST_F(CommonOperatorTest,BeginRegion)364 TEST_F(CommonOperatorTest, BeginRegion) {
365   const Operator* op = common()->BeginRegion();
366   EXPECT_EQ(1, op->EffectInputCount());
367   EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op));
368   EXPECT_EQ(0, op->ControlOutputCount());
369   EXPECT_EQ(1, op->EffectOutputCount());
370   EXPECT_EQ(0, op->ValueOutputCount());
371 }
372 
373 
TEST_F(CommonOperatorTest,FinishRegion)374 TEST_F(CommonOperatorTest, FinishRegion) {
375   const Operator* op = common()->FinishRegion();
376   EXPECT_EQ(1, op->ValueInputCount());
377   EXPECT_EQ(1, op->EffectInputCount());
378   EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op));
379   EXPECT_EQ(0, op->ControlOutputCount());
380   EXPECT_EQ(1, op->EffectOutputCount());
381   EXPECT_EQ(1, op->ValueOutputCount());
382 }
383 
384 }  // namespace compiler
385 }  // namespace internal
386 }  // namespace v8
387