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 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 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 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 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 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: 122 CommonOperatorTest() : common_(zone()) {} 123 ~CommonOperatorTest() override {} 124 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 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 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 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 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 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 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 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 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 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 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 364 TEST_F(CommonOperatorTest, BeginRegion) { 365 { 366 const Operator* op = 367 common()->BeginRegion(RegionObservability::kObservable); 368 EXPECT_EQ(1, op->EffectInputCount()); 369 EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op)); 370 EXPECT_EQ(0, op->ControlOutputCount()); 371 EXPECT_EQ(1, op->EffectOutputCount()); 372 EXPECT_EQ(0, op->ValueOutputCount()); 373 } 374 { 375 const Operator* op = 376 common()->BeginRegion(RegionObservability::kNotObservable); 377 EXPECT_EQ(1, op->EffectInputCount()); 378 EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op)); 379 EXPECT_EQ(0, op->ControlOutputCount()); 380 EXPECT_EQ(1, op->EffectOutputCount()); 381 EXPECT_EQ(0, op->ValueOutputCount()); 382 } 383 } 384 385 TEST_F(CommonOperatorTest, FinishRegion) { 386 const Operator* op = common()->FinishRegion(); 387 EXPECT_EQ(1, op->ValueInputCount()); 388 EXPECT_EQ(1, op->EffectInputCount()); 389 EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op)); 390 EXPECT_EQ(0, op->ControlOutputCount()); 391 EXPECT_EQ(1, op->EffectOutputCount()); 392 EXPECT_EQ(1, op->ValueOutputCount()); 393 } 394 395 TEST_F(CommonOperatorTest, Projection) { 396 TRACED_FORRANGE(size_t, index, 0, 3) { 397 const Operator* op = common()->Projection(index); 398 EXPECT_EQ(index, ProjectionIndexOf(op)); 399 EXPECT_EQ(1, op->ValueInputCount()); 400 EXPECT_EQ(1, op->ControlInputCount()); 401 EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op)); 402 EXPECT_EQ(0, op->ControlOutputCount()); 403 EXPECT_EQ(0, op->EffectOutputCount()); 404 EXPECT_EQ(1, op->ValueOutputCount()); 405 } 406 } 407 408 } // namespace compiler 409 } // namespace internal 410 } // namespace v8 411