OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/machine-operator.h" | 5 #include "src/compiler/machine-operator.h" |
6 #include "src/compiler/operator-properties-inl.h" | 6 #include "src/compiler/operator-properties-inl.h" |
7 #include "src/test/test-utils.h" | 7 #include "testing/gtest-support.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
11 namespace compiler { | 11 namespace compiler { |
12 | 12 |
13 class MachineOperatorCommonTest | 13 #if GTEST_HAS_COMBINE |
14 : public TestWithZone, | 14 |
15 public ::testing::WithParamInterface<MachineType> { | 15 // TODO(bmeurer): Find a new home for these. |
16 public: | 16 inline std::ostream& operator<<(std::ostream& os, const MachineType& type) { |
17 MachineOperatorCommonTest() : machine_(NULL) {} | 17 OStringStream ost; |
18 virtual ~MachineOperatorCommonTest() { EXPECT_EQ(NULL, machine_); } | 18 ost << type; |
19 | 19 return os << ost.c_str(); |
20 virtual void SetUp() OVERRIDE { | 20 } |
21 TestWithZone::SetUp(); | 21 inline std::ostream& operator<<(std::ostream& os, |
22 EXPECT_EQ(NULL, machine_); | 22 const WriteBarrierKind& write_barrier_kind) { |
23 machine_ = new MachineOperatorBuilder(zone(), GetParam()); | 23 OStringStream ost; |
| 24 ost << write_barrier_kind; |
| 25 return os << ost.c_str(); |
| 26 } |
| 27 |
| 28 |
| 29 template <typename T> |
| 30 class MachineOperatorTestWithParam |
| 31 : public ::testing::TestWithParam< ::testing::tuple<MachineType, T> > { |
| 32 protected: |
| 33 MachineType type() const { return ::testing::get<0>(B::GetParam()); } |
| 34 const T& GetParam() const { return ::testing::get<1>(B::GetParam()); } |
| 35 |
| 36 private: |
| 37 typedef ::testing::TestWithParam< ::testing::tuple<MachineType, T> > B; |
| 38 }; |
| 39 |
| 40 |
| 41 namespace { |
| 42 |
| 43 const MachineType kMachineReps[] = {kRepWord32, kRepWord64}; |
| 44 |
| 45 |
| 46 const MachineType kMachineTypes[] = { |
| 47 kMachFloat32, kMachFloat64, kMachInt8, kMachUint8, kMachInt16, |
| 48 kMachUint16, kMachInt32, kMachUint32, kMachInt64, kMachUint64, |
| 49 kMachPtr, kMachAnyTagged, kRepBit, kRepWord8, kRepWord16, |
| 50 kRepWord32, kRepWord64, kRepFloat32, kRepFloat64, kRepTagged}; |
| 51 |
| 52 } // namespace |
| 53 |
| 54 |
| 55 // ----------------------------------------------------------------------------- |
| 56 // Load operator. |
| 57 |
| 58 |
| 59 typedef MachineOperatorTestWithParam<LoadRepresentation> |
| 60 MachineLoadOperatorTest; |
| 61 |
| 62 |
| 63 TEST_P(MachineLoadOperatorTest, InstancesAreGloballyShared) { |
| 64 MachineOperatorBuilder machine1(type()); |
| 65 MachineOperatorBuilder machine2(type()); |
| 66 EXPECT_EQ(machine1.Load(GetParam()), machine2.Load(GetParam())); |
| 67 } |
| 68 |
| 69 |
| 70 TEST_P(MachineLoadOperatorTest, NumberOfInputsAndOutputs) { |
| 71 MachineOperatorBuilder machine(type()); |
| 72 const Operator* op = machine.Load(GetParam()); |
| 73 |
| 74 EXPECT_EQ(2, OperatorProperties::GetValueInputCount(op)); |
| 75 EXPECT_EQ(1, OperatorProperties::GetEffectInputCount(op)); |
| 76 EXPECT_EQ(0, OperatorProperties::GetControlInputCount(op)); |
| 77 EXPECT_EQ(3, OperatorProperties::GetTotalInputCount(op)); |
| 78 |
| 79 EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op)); |
| 80 EXPECT_EQ(1, OperatorProperties::GetEffectOutputCount(op)); |
| 81 EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op)); |
| 82 } |
| 83 |
| 84 |
| 85 TEST_P(MachineLoadOperatorTest, OpcodeIsCorrect) { |
| 86 MachineOperatorBuilder machine(type()); |
| 87 EXPECT_EQ(IrOpcode::kLoad, machine.Load(GetParam())->opcode()); |
| 88 } |
| 89 |
| 90 |
| 91 TEST_P(MachineLoadOperatorTest, ParameterIsCorrect) { |
| 92 MachineOperatorBuilder machine(type()); |
| 93 EXPECT_EQ(GetParam(), |
| 94 OpParameter<LoadRepresentation>(machine.Load(GetParam()))); |
| 95 } |
| 96 |
| 97 |
| 98 INSTANTIATE_TEST_CASE_P(MachineOperatorTest, MachineLoadOperatorTest, |
| 99 ::testing::Combine(::testing::ValuesIn(kMachineReps), |
| 100 ::testing::ValuesIn(kMachineTypes))); |
| 101 |
| 102 |
| 103 // ----------------------------------------------------------------------------- |
| 104 // Store operator. |
| 105 |
| 106 |
| 107 class MachineStoreOperatorTest |
| 108 : public MachineOperatorTestWithParam< |
| 109 ::testing::tuple<MachineType, WriteBarrierKind> > { |
| 110 protected: |
| 111 StoreRepresentation GetParam() const { |
| 112 return StoreRepresentation( |
| 113 ::testing::get<0>(MachineOperatorTestWithParam< |
| 114 ::testing::tuple<MachineType, WriteBarrierKind> >::GetParam()), |
| 115 ::testing::get<1>(MachineOperatorTestWithParam< |
| 116 ::testing::tuple<MachineType, WriteBarrierKind> >::GetParam())); |
24 } | 117 } |
25 | 118 }; |
26 virtual void TearDown() OVERRIDE { | 119 |
27 ASSERT_TRUE(machine_ != NULL); | 120 |
28 delete machine_; | 121 TEST_P(MachineStoreOperatorTest, InstancesAreGloballyShared) { |
29 machine_ = NULL; | 122 MachineOperatorBuilder machine1(type()); |
30 TestWithZone::TearDown(); | 123 MachineOperatorBuilder machine2(type()); |
| 124 EXPECT_EQ(machine1.Store(GetParam()), machine2.Store(GetParam())); |
| 125 } |
| 126 |
| 127 |
| 128 TEST_P(MachineStoreOperatorTest, NumberOfInputsAndOutputs) { |
| 129 MachineOperatorBuilder machine(type()); |
| 130 const Operator* op = machine.Store(GetParam()); |
| 131 |
| 132 EXPECT_EQ(3, OperatorProperties::GetValueInputCount(op)); |
| 133 EXPECT_EQ(1, OperatorProperties::GetEffectInputCount(op)); |
| 134 EXPECT_EQ(1, OperatorProperties::GetControlInputCount(op)); |
| 135 EXPECT_EQ(5, OperatorProperties::GetTotalInputCount(op)); |
| 136 |
| 137 EXPECT_EQ(0, OperatorProperties::GetValueOutputCount(op)); |
| 138 EXPECT_EQ(1, OperatorProperties::GetEffectOutputCount(op)); |
| 139 EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op)); |
| 140 } |
| 141 |
| 142 |
| 143 TEST_P(MachineStoreOperatorTest, OpcodeIsCorrect) { |
| 144 MachineOperatorBuilder machine(type()); |
| 145 EXPECT_EQ(IrOpcode::kStore, machine.Store(GetParam())->opcode()); |
| 146 } |
| 147 |
| 148 |
| 149 TEST_P(MachineStoreOperatorTest, ParameterIsCorrect) { |
| 150 MachineOperatorBuilder machine(type()); |
| 151 EXPECT_EQ(GetParam(), |
| 152 OpParameter<StoreRepresentation>(machine.Store(GetParam()))); |
| 153 } |
| 154 |
| 155 |
| 156 INSTANTIATE_TEST_CASE_P( |
| 157 MachineOperatorTest, MachineStoreOperatorTest, |
| 158 ::testing::Combine( |
| 159 ::testing::ValuesIn(kMachineReps), |
| 160 ::testing::Combine(::testing::ValuesIn(kMachineTypes), |
| 161 ::testing::Values(kNoWriteBarrier, |
| 162 kFullWriteBarrier)))); |
| 163 |
| 164 |
| 165 // ----------------------------------------------------------------------------- |
| 166 // Pure operators. |
| 167 |
| 168 |
| 169 namespace { |
| 170 |
| 171 struct PureOperator { |
| 172 const Operator* (MachineOperatorBuilder::*constructor)(); |
| 173 IrOpcode::Value opcode; |
| 174 int value_input_count; |
| 175 int value_output_count; |
| 176 }; |
| 177 |
| 178 |
| 179 std::ostream& operator<<(std::ostream& os, const PureOperator& pop) { |
| 180 return os << IrOpcode::Mnemonic(pop.opcode); |
| 181 } |
| 182 |
| 183 |
| 184 const PureOperator kPureOperators[] = { |
| 185 #define PURE(Name, input_count, output_count) \ |
| 186 { \ |
| 187 &MachineOperatorBuilder::Name, IrOpcode::k##Name, input_count, \ |
| 188 output_count \ |
31 } | 189 } |
32 | 190 PURE(Word32And, 2, 1), PURE(Word32Or, 2, 1), |
33 protected: | 191 PURE(Word32Xor, 2, 1), PURE(Word32Shl, 2, 1), |
34 MachineOperatorBuilder* machine() const { return machine_; } | 192 PURE(Word32Shr, 2, 1), PURE(Word32Sar, 2, 1), |
35 | 193 PURE(Word32Ror, 2, 1), PURE(Word32Equal, 2, 1), |
36 private: | 194 PURE(Word64And, 2, 1), PURE(Word64Or, 2, 1), |
37 MachineOperatorBuilder* machine_; | 195 PURE(Word64Xor, 2, 1), PURE(Word64Shl, 2, 1), |
| 196 PURE(Word64Shr, 2, 1), PURE(Word64Sar, 2, 1), |
| 197 PURE(Word64Ror, 2, 1), PURE(Word64Equal, 2, 1), |
| 198 PURE(Int32Add, 2, 1), PURE(Int32AddWithOverflow, 2, 2), |
| 199 PURE(Int32Sub, 2, 1), PURE(Int32SubWithOverflow, 2, 2), |
| 200 PURE(Int32Mul, 2, 1), PURE(Int32Div, 2, 1), |
| 201 PURE(Int32UDiv, 2, 1), PURE(Int32Mod, 2, 1), |
| 202 PURE(Int32UMod, 2, 1), PURE(Int32LessThan, 2, 1), |
| 203 PURE(Int32LessThanOrEqual, 2, 1), PURE(Uint32LessThan, 2, 1), |
| 204 PURE(Uint32LessThanOrEqual, 2, 1), PURE(Int64Add, 2, 1), |
| 205 PURE(Int64Sub, 2, 1), PURE(Int64Mul, 2, 1), |
| 206 PURE(Int64Div, 2, 1), PURE(Int64UDiv, 2, 1), |
| 207 PURE(Int64Mod, 2, 1), PURE(Int64UMod, 2, 1), |
| 208 PURE(Int64LessThan, 2, 1), PURE(Int64LessThanOrEqual, 2, 1), |
| 209 PURE(ChangeFloat64ToInt32, 1, 1), PURE(ChangeFloat64ToUint32, 1, 1), |
| 210 PURE(ChangeInt32ToInt64, 1, 1), PURE(ChangeUint32ToFloat64, 1, 1), |
| 211 PURE(ChangeUint32ToUint64, 1, 1), PURE(TruncateFloat64ToInt32, 1, 1), |
| 212 PURE(TruncateInt64ToInt32, 1, 1), PURE(Float64Add, 2, 1), |
| 213 PURE(Float64Sub, 2, 1), PURE(Float64Mul, 2, 1), |
| 214 PURE(Float64Div, 2, 1), PURE(Float64Mod, 2, 1), |
| 215 PURE(Float64Equal, 2, 1), PURE(Float64LessThan, 2, 1), |
| 216 PURE(Float64LessThanOrEqual, 2, 1) |
| 217 #undef PURE |
38 }; | 218 }; |
39 | 219 |
40 | 220 |
41 TEST_P(MachineOperatorCommonTest, ChangeInt32ToInt64) { | 221 typedef MachineOperatorTestWithParam<PureOperator> MachinePureOperatorTest; |
42 const Operator* op = machine()->ChangeInt32ToInt64(); | 222 |
43 EXPECT_EQ(1, OperatorProperties::GetValueInputCount(op)); | 223 } // namespace |
44 EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op)); | 224 |
| 225 |
| 226 TEST_P(MachinePureOperatorTest, InstancesAreGloballyShared) { |
| 227 const PureOperator& pop = GetParam(); |
| 228 MachineOperatorBuilder machine1(type()); |
| 229 MachineOperatorBuilder machine2(type()); |
| 230 EXPECT_EQ((machine1.*pop.constructor)(), (machine2.*pop.constructor)()); |
| 231 } |
| 232 |
| 233 |
| 234 TEST_P(MachinePureOperatorTest, NumberOfInputsAndOutputs) { |
| 235 MachineOperatorBuilder machine(type()); |
| 236 const PureOperator& pop = GetParam(); |
| 237 const Operator* op = (machine.*pop.constructor)(); |
| 238 |
| 239 EXPECT_EQ(pop.value_input_count, OperatorProperties::GetValueInputCount(op)); |
| 240 EXPECT_EQ(0, OperatorProperties::GetEffectInputCount(op)); |
| 241 EXPECT_EQ(0, OperatorProperties::GetControlInputCount(op)); |
| 242 EXPECT_EQ(pop.value_input_count, OperatorProperties::GetTotalInputCount(op)); |
| 243 |
| 244 EXPECT_EQ(pop.value_output_count, |
| 245 OperatorProperties::GetValueOutputCount(op)); |
| 246 EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op)); |
45 EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op)); | 247 EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op)); |
46 EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op)); | 248 } |
47 EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op)); | 249 |
48 } | 250 |
49 | 251 TEST_P(MachinePureOperatorTest, MarkedAsPure) { |
50 | 252 MachineOperatorBuilder machine(type()); |
51 TEST_P(MachineOperatorCommonTest, ChangeUint32ToUint64) { | 253 const PureOperator& pop = GetParam(); |
52 const Operator* op = machine()->ChangeUint32ToUint64(); | 254 const Operator* op = (machine.*pop.constructor)(); |
53 EXPECT_EQ(1, OperatorProperties::GetValueInputCount(op)); | 255 EXPECT_TRUE(op->HasProperty(Operator::kPure)); |
54 EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op)); | 256 } |
55 EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op)); | 257 |
56 EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op)); | 258 |
57 EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op)); | 259 TEST_P(MachinePureOperatorTest, OpcodeIsCorrect) { |
58 } | 260 MachineOperatorBuilder machine(type()); |
59 | 261 const PureOperator& pop = GetParam(); |
60 | 262 const Operator* op = (machine.*pop.constructor)(); |
61 TEST_P(MachineOperatorCommonTest, TruncateFloat64ToInt32) { | 263 EXPECT_EQ(pop.opcode, op->opcode()); |
62 const Operator* op = machine()->TruncateFloat64ToInt32(); | 264 } |
63 EXPECT_EQ(1, OperatorProperties::GetValueInputCount(op)); | 265 |
64 EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op)); | 266 |
65 EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op)); | 267 INSTANTIATE_TEST_CASE_P( |
66 EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op)); | 268 MachineOperatorTest, MachinePureOperatorTest, |
67 EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op)); | 269 ::testing::Combine(::testing::ValuesIn(kMachineReps), |
68 } | 270 ::testing::ValuesIn(kPureOperators))); |
69 | 271 |
70 | 272 #endif // GTEST_HAS_COMBINE |
71 TEST_P(MachineOperatorCommonTest, TruncateInt64ToInt32) { | 273 |
72 const Operator* op = machine()->TruncateInt64ToInt32(); | 274 |
73 EXPECT_EQ(1, OperatorProperties::GetValueInputCount(op)); | 275 // ----------------------------------------------------------------------------- |
74 EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op)); | 276 // Pseudo operators. |
75 EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op)); | 277 |
76 EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op)); | 278 |
77 EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op)); | 279 TEST(MachineOperatorTest, PseudoOperatorsWhenWordSizeIs32Bit) { |
78 } | 280 MachineOperatorBuilder machine(kRepWord32); |
79 | 281 EXPECT_EQ(machine.Word32And(), machine.WordAnd()); |
80 | 282 EXPECT_EQ(machine.Word32Or(), machine.WordOr()); |
81 INSTANTIATE_TEST_CASE_P(MachineOperatorTest, MachineOperatorCommonTest, | 283 EXPECT_EQ(machine.Word32Xor(), machine.WordXor()); |
82 ::testing::Values(kRepWord32, kRepWord64)); | 284 EXPECT_EQ(machine.Word32Shl(), machine.WordShl()); |
| 285 EXPECT_EQ(machine.Word32Shr(), machine.WordShr()); |
| 286 EXPECT_EQ(machine.Word32Sar(), machine.WordSar()); |
| 287 EXPECT_EQ(machine.Word32Ror(), machine.WordRor()); |
| 288 EXPECT_EQ(machine.Word32Equal(), machine.WordEqual()); |
| 289 EXPECT_EQ(machine.Int32Add(), machine.IntAdd()); |
| 290 EXPECT_EQ(machine.Int32Sub(), machine.IntSub()); |
| 291 EXPECT_EQ(machine.Int32Mul(), machine.IntMul()); |
| 292 EXPECT_EQ(machine.Int32Div(), machine.IntDiv()); |
| 293 EXPECT_EQ(machine.Int32UDiv(), machine.IntUDiv()); |
| 294 EXPECT_EQ(machine.Int32Mod(), machine.IntMod()); |
| 295 EXPECT_EQ(machine.Int32UMod(), machine.IntUMod()); |
| 296 EXPECT_EQ(machine.Int32LessThan(), machine.IntLessThan()); |
| 297 EXPECT_EQ(machine.Int32LessThanOrEqual(), machine.IntLessThanOrEqual()); |
| 298 } |
| 299 |
| 300 |
| 301 TEST(MachineOperatorTest, PseudoOperatorsWhenWordSizeIs64Bit) { |
| 302 MachineOperatorBuilder machine(kRepWord64); |
| 303 EXPECT_EQ(machine.Word64And(), machine.WordAnd()); |
| 304 EXPECT_EQ(machine.Word64Or(), machine.WordOr()); |
| 305 EXPECT_EQ(machine.Word64Xor(), machine.WordXor()); |
| 306 EXPECT_EQ(machine.Word64Shl(), machine.WordShl()); |
| 307 EXPECT_EQ(machine.Word64Shr(), machine.WordShr()); |
| 308 EXPECT_EQ(machine.Word64Sar(), machine.WordSar()); |
| 309 EXPECT_EQ(machine.Word64Ror(), machine.WordRor()); |
| 310 EXPECT_EQ(machine.Word64Equal(), machine.WordEqual()); |
| 311 EXPECT_EQ(machine.Int64Add(), machine.IntAdd()); |
| 312 EXPECT_EQ(machine.Int64Sub(), machine.IntSub()); |
| 313 EXPECT_EQ(machine.Int64Mul(), machine.IntMul()); |
| 314 EXPECT_EQ(machine.Int64Div(), machine.IntDiv()); |
| 315 EXPECT_EQ(machine.Int64UDiv(), machine.IntUDiv()); |
| 316 EXPECT_EQ(machine.Int64Mod(), machine.IntMod()); |
| 317 EXPECT_EQ(machine.Int64UMod(), machine.IntUMod()); |
| 318 EXPECT_EQ(machine.Int64LessThan(), machine.IntLessThan()); |
| 319 EXPECT_EQ(machine.Int64LessThanOrEqual(), machine.IntLessThanOrEqual()); |
| 320 } |
83 | 321 |
84 } // namespace compiler | 322 } // namespace compiler |
85 } // namespace internal | 323 } // namespace internal |
86 } // namespace v8 | 324 } // namespace v8 |
OLD | NEW |