1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/compiler/common-operator.h"
6 
7 #include <limits>
8 
9 #include "src/compiler/operator-properties-inl.h"
10 #include "src/test/test-utils.h"
11 
12 namespace v8 {
13 namespace internal {
14 namespace compiler {
15 
16 
17 // -----------------------------------------------------------------------------
18 // Shared operators.
19 
20 
21 namespace {
22 
23 struct SharedOperator {
24   const Operator* (CommonOperatorBuilder::*constructor)();
25   IrOpcode::Value opcode;
26   Operator::Properties properties;
27   int value_input_count;
28   int effect_input_count;
29   int control_input_count;
30   int effect_output_count;
31   int control_output_count;
32 };
33 
34 
operator <<(std::ostream & os,const SharedOperator & fop)35 std::ostream& operator<<(std::ostream& os, const SharedOperator& fop) {
36   return os << IrOpcode::Mnemonic(fop.opcode);
37 }
38 
39 
40 const SharedOperator kSharedOperators[] = {
41 #define SHARED(Name, properties, value_input_count, effect_input_count,        \
42                control_input_count, effect_output_count, control_output_count) \
43   {                                                                            \
44     &CommonOperatorBuilder::Name, IrOpcode::k##Name, properties,               \
45         value_input_count, effect_input_count, control_input_count,            \
46         effect_output_count, control_output_count                              \
47   }
48     SHARED(Dead, Operator::kFoldable, 0, 0, 0, 0, 1),
49     SHARED(End, Operator::kFoldable, 0, 0, 1, 0, 0),
50     SHARED(Branch, Operator::kFoldable, 1, 0, 1, 0, 2),
51     SHARED(IfTrue, Operator::kFoldable, 0, 0, 1, 0, 1),
52     SHARED(IfFalse, Operator::kFoldable, 0, 0, 1, 0, 1),
53     SHARED(Throw, Operator::kFoldable, 1, 0, 1, 0, 1),
54     SHARED(Return, Operator::kNoProperties, 1, 1, 1, 1, 1),
55     SHARED(ControlEffect, Operator::kPure, 0, 0, 1, 1, 0)
56 #undef SHARED
57 };
58 
59 
60 class CommonSharedOperatorTest
61     : public TestWithZone,
62       public ::testing::WithParamInterface<SharedOperator> {};
63 
64 }  // namespace
65 
66 
TEST_P(CommonSharedOperatorTest,InstancesAreGloballyShared)67 TEST_P(CommonSharedOperatorTest, InstancesAreGloballyShared) {
68   const SharedOperator& sop = GetParam();
69   CommonOperatorBuilder common1(zone());
70   CommonOperatorBuilder common2(zone());
71   EXPECT_EQ((common1.*sop.constructor)(), (common2.*sop.constructor)());
72 }
73 
74 
TEST_P(CommonSharedOperatorTest,NumberOfInputsAndOutputs)75 TEST_P(CommonSharedOperatorTest, NumberOfInputsAndOutputs) {
76   CommonOperatorBuilder common(zone());
77   const SharedOperator& sop = GetParam();
78   const Operator* op = (common.*sop.constructor)();
79 
80   EXPECT_EQ(sop.value_input_count, OperatorProperties::GetValueInputCount(op));
81   EXPECT_EQ(sop.effect_input_count,
82             OperatorProperties::GetEffectInputCount(op));
83   EXPECT_EQ(sop.control_input_count,
84             OperatorProperties::GetControlInputCount(op));
85   EXPECT_EQ(
86       sop.value_input_count + sop.effect_input_count + sop.control_input_count,
87       OperatorProperties::GetTotalInputCount(op));
88 
89   EXPECT_EQ(0, OperatorProperties::GetValueOutputCount(op));
90   EXPECT_EQ(sop.effect_output_count,
91             OperatorProperties::GetEffectOutputCount(op));
92   EXPECT_EQ(sop.control_output_count,
93             OperatorProperties::GetControlOutputCount(op));
94 }
95 
96 
TEST_P(CommonSharedOperatorTest,OpcodeIsCorrect)97 TEST_P(CommonSharedOperatorTest, OpcodeIsCorrect) {
98   CommonOperatorBuilder common(zone());
99   const SharedOperator& sop = GetParam();
100   const Operator* op = (common.*sop.constructor)();
101   EXPECT_EQ(sop.opcode, op->opcode());
102 }
103 
104 
TEST_P(CommonSharedOperatorTest,Properties)105 TEST_P(CommonSharedOperatorTest, Properties) {
106   CommonOperatorBuilder common(zone());
107   const SharedOperator& sop = GetParam();
108   const Operator* op = (common.*sop.constructor)();
109   EXPECT_EQ(sop.properties, op->properties());
110 }
111 
112 
113 INSTANTIATE_TEST_CASE_P(CommonOperatorTest, CommonSharedOperatorTest,
114                         ::testing::ValuesIn(kSharedOperators));
115 
116 
117 // -----------------------------------------------------------------------------
118 // Other operators.
119 
120 
121 namespace {
122 
123 class CommonOperatorTest : public TestWithZone {
124  public:
CommonOperatorTest()125   CommonOperatorTest() : common_(zone()) {}
~CommonOperatorTest()126   virtual ~CommonOperatorTest() {}
127 
common()128   CommonOperatorBuilder* common() { return &common_; }
129 
130  private:
131   CommonOperatorBuilder common_;
132 };
133 
134 
135 const int kArguments[] = {1, 5, 6, 42, 100, 10000, kMaxInt};
136 
137 const float kFloat32Values[] = {
138     std::numeric_limits<float>::min(), -1.0f, -0.0f, 0.0f, 1.0f,
139     std::numeric_limits<float>::max()};
140 
141 }  // namespace
142 
143 
TEST_F(CommonOperatorTest,Float32Constant)144 TEST_F(CommonOperatorTest, Float32Constant) {
145   TRACED_FOREACH(float, value, kFloat32Values) {
146     const Operator* op = common()->Float32Constant(value);
147     EXPECT_FLOAT_EQ(value, OpParameter<float>(op));
148     EXPECT_EQ(0, OperatorProperties::GetValueInputCount(op));
149     EXPECT_EQ(0, OperatorProperties::GetTotalInputCount(op));
150     EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
151     EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op));
152     EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op));
153   }
154 }
155 
156 
TEST_F(CommonOperatorTest,ValueEffect)157 TEST_F(CommonOperatorTest, ValueEffect) {
158   TRACED_FOREACH(int, arguments, kArguments) {
159     const Operator* op = common()->ValueEffect(arguments);
160     EXPECT_EQ(arguments, OperatorProperties::GetValueInputCount(op));
161     EXPECT_EQ(arguments, OperatorProperties::GetTotalInputCount(op));
162     EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
163     EXPECT_EQ(1, OperatorProperties::GetEffectOutputCount(op));
164     EXPECT_EQ(0, OperatorProperties::GetValueOutputCount(op));
165   }
166 }
167 
168 
TEST_F(CommonOperatorTest,Finish)169 TEST_F(CommonOperatorTest, Finish) {
170   TRACED_FOREACH(int, arguments, kArguments) {
171     const Operator* op = common()->Finish(arguments);
172     EXPECT_EQ(1, OperatorProperties::GetValueInputCount(op));
173     EXPECT_EQ(arguments, OperatorProperties::GetEffectInputCount(op));
174     EXPECT_EQ(arguments + 1, OperatorProperties::GetTotalInputCount(op));
175     EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
176     EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op));
177     EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op));
178   }
179 }
180 
181 }  // namespace compiler
182 }  // namespace internal
183 }  // namespace v8
184