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 #include "src/compiler/common-operator-reducer.h" 7 #include "src/compiler/machine-operator.h" 8 #include "src/compiler/operator.h" 9 #include "src/compiler/simplified-operator.h" 10 #include "src/machine-type.h" 11 #include "test/unittests/compiler/graph-reducer-unittest.h" 12 #include "test/unittests/compiler/graph-unittest.h" 13 #include "test/unittests/compiler/node-test-utils.h" 14 15 using testing::StrictMock; 16 17 namespace v8 { 18 namespace internal { 19 namespace compiler { 20 21 class CommonOperatorReducerTest : public GraphTest { 22 public: 23 explicit CommonOperatorReducerTest(int num_parameters = 1) 24 : GraphTest(num_parameters), machine_(zone()), simplified_(zone()) {} 25 ~CommonOperatorReducerTest() override {} 26 27 protected: 28 Reduction Reduce( 29 AdvancedReducer::Editor* editor, Node* node, 30 MachineOperatorBuilder::Flags flags = MachineOperatorBuilder::kNoFlags) { 31 MachineOperatorBuilder machine(zone(), MachineType::PointerRepresentation(), 32 flags); 33 CommonOperatorReducer reducer(editor, graph(), common(), &machine); 34 return reducer.Reduce(node); 35 } 36 37 Reduction Reduce(Node* node, MachineOperatorBuilder::Flags flags = 38 MachineOperatorBuilder::kNoFlags) { 39 StrictMock<MockAdvancedReducerEditor> editor; 40 return Reduce(&editor, node, flags); 41 } 42 43 MachineOperatorBuilder* machine() { return &machine_; } 44 SimplifiedOperatorBuilder* simplified() { return &simplified_; } 45 46 private: 47 MachineOperatorBuilder machine_; 48 SimplifiedOperatorBuilder simplified_; 49 }; 50 51 52 namespace { 53 54 const BranchHint kBranchHints[] = {BranchHint::kNone, BranchHint::kFalse, 55 BranchHint::kTrue}; 56 57 58 const MachineRepresentation kMachineRepresentations[] = { 59 MachineRepresentation::kBit, MachineRepresentation::kWord8, 60 MachineRepresentation::kWord16, MachineRepresentation::kWord32, 61 MachineRepresentation::kWord64, MachineRepresentation::kFloat32, 62 MachineRepresentation::kFloat64, MachineRepresentation::kTagged}; 63 64 65 const Operator kOp0(0, Operator::kNoProperties, "Op0", 0, 0, 0, 1, 1, 0); 66 67 } // namespace 68 69 70 // ----------------------------------------------------------------------------- 71 // Branch 72 73 74 TEST_F(CommonOperatorReducerTest, BranchWithInt32ZeroConstant) { 75 TRACED_FOREACH(BranchHint, hint, kBranchHints) { 76 Node* const control = graph()->start(); 77 Node* const branch = 78 graph()->NewNode(common()->Branch(hint), Int32Constant(0), control); 79 Node* const if_true = graph()->NewNode(common()->IfTrue(), branch); 80 Node* const if_false = graph()->NewNode(common()->IfFalse(), branch); 81 StrictMock<MockAdvancedReducerEditor> editor; 82 EXPECT_CALL(editor, Replace(if_true, IsDead())); 83 EXPECT_CALL(editor, Replace(if_false, control)); 84 Reduction const r = Reduce(&editor, branch); 85 ASSERT_TRUE(r.Changed()); 86 EXPECT_THAT(r.replacement(), IsDead()); 87 } 88 } 89 90 91 TEST_F(CommonOperatorReducerTest, BranchWithInt32OneConstant) { 92 TRACED_FOREACH(BranchHint, hint, kBranchHints) { 93 Node* const control = graph()->start(); 94 Node* const branch = 95 graph()->NewNode(common()->Branch(hint), Int32Constant(1), control); 96 Node* const if_true = graph()->NewNode(common()->IfTrue(), branch); 97 Node* const if_false = graph()->NewNode(common()->IfFalse(), branch); 98 StrictMock<MockAdvancedReducerEditor> editor; 99 EXPECT_CALL(editor, Replace(if_true, control)); 100 EXPECT_CALL(editor, Replace(if_false, IsDead())); 101 Reduction const r = Reduce(&editor, branch); 102 ASSERT_TRUE(r.Changed()); 103 EXPECT_THAT(r.replacement(), IsDead()); 104 } 105 } 106 107 108 TEST_F(CommonOperatorReducerTest, BranchWithFalseConstant) { 109 TRACED_FOREACH(BranchHint, hint, kBranchHints) { 110 Node* const control = graph()->start(); 111 Node* const branch = 112 graph()->NewNode(common()->Branch(hint), FalseConstant(), control); 113 Node* const if_true = graph()->NewNode(common()->IfTrue(), branch); 114 Node* const if_false = graph()->NewNode(common()->IfFalse(), branch); 115 StrictMock<MockAdvancedReducerEditor> editor; 116 EXPECT_CALL(editor, Replace(if_true, IsDead())); 117 EXPECT_CALL(editor, Replace(if_false, control)); 118 Reduction const r = Reduce(&editor, branch); 119 ASSERT_TRUE(r.Changed()); 120 EXPECT_THAT(r.replacement(), IsDead()); 121 } 122 } 123 124 125 TEST_F(CommonOperatorReducerTest, BranchWithTrueConstant) { 126 TRACED_FOREACH(BranchHint, hint, kBranchHints) { 127 Node* const control = graph()->start(); 128 Node* const branch = 129 graph()->NewNode(common()->Branch(hint), TrueConstant(), control); 130 Node* const if_true = graph()->NewNode(common()->IfTrue(), branch); 131 Node* const if_false = graph()->NewNode(common()->IfFalse(), branch); 132 StrictMock<MockAdvancedReducerEditor> editor; 133 EXPECT_CALL(editor, Replace(if_true, control)); 134 EXPECT_CALL(editor, Replace(if_false, IsDead())); 135 Reduction const r = Reduce(&editor, branch); 136 ASSERT_TRUE(r.Changed()); 137 EXPECT_THAT(r.replacement(), IsDead()); 138 } 139 } 140 141 142 TEST_F(CommonOperatorReducerTest, BranchWithBooleanNot) { 143 Node* const value = Parameter(0); 144 TRACED_FOREACH(BranchHint, hint, kBranchHints) { 145 Node* const control = graph()->start(); 146 Node* const branch = graph()->NewNode( 147 common()->Branch(hint), 148 graph()->NewNode(simplified()->BooleanNot(), value), control); 149 Node* const if_true = graph()->NewNode(common()->IfTrue(), branch); 150 Node* const if_false = graph()->NewNode(common()->IfFalse(), branch); 151 Reduction const r = Reduce(branch); 152 ASSERT_TRUE(r.Changed()); 153 EXPECT_EQ(branch, r.replacement()); 154 EXPECT_THAT(branch, IsBranch(value, control)); 155 EXPECT_THAT(if_false, IsIfTrue(branch)); 156 EXPECT_THAT(if_true, IsIfFalse(branch)); 157 EXPECT_EQ(NegateBranchHint(hint), BranchHintOf(branch->op())); 158 } 159 } 160 161 162 // ----------------------------------------------------------------------------- 163 // Merge 164 165 166 TEST_F(CommonOperatorReducerTest, MergeOfUnusedDiamond0) { 167 Node* const value = Parameter(0); 168 Node* const control = graph()->start(); 169 Node* const branch = graph()->NewNode(common()->Branch(), value, control); 170 Node* const if_true = graph()->NewNode(common()->IfTrue(), branch); 171 Node* const if_false = graph()->NewNode(common()->IfFalse(), branch); 172 Reduction const r = 173 Reduce(graph()->NewNode(common()->Merge(2), if_true, if_false)); 174 ASSERT_TRUE(r.Changed()); 175 EXPECT_EQ(control, r.replacement()); 176 EXPECT_THAT(branch, IsDead()); 177 } 178 179 180 TEST_F(CommonOperatorReducerTest, MergeOfUnusedDiamond1) { 181 Node* const value = Parameter(0); 182 Node* const control = graph()->start(); 183 Node* const branch = graph()->NewNode(common()->Branch(), value, control); 184 Node* const if_true = graph()->NewNode(common()->IfTrue(), branch); 185 Node* const if_false = graph()->NewNode(common()->IfFalse(), branch); 186 Reduction const r = 187 Reduce(graph()->NewNode(common()->Merge(2), if_false, if_true)); 188 ASSERT_TRUE(r.Changed()); 189 EXPECT_EQ(control, r.replacement()); 190 EXPECT_THAT(branch, IsDead()); 191 } 192 193 194 // ----------------------------------------------------------------------------- 195 // EffectPhi 196 197 198 TEST_F(CommonOperatorReducerTest, EffectPhiWithMerge) { 199 const int kMaxInputs = 64; 200 Node* inputs[kMaxInputs]; 201 Node* const input = graph()->NewNode(&kOp0); 202 TRACED_FORRANGE(int, input_count, 2, kMaxInputs - 1) { 203 int const value_input_count = input_count - 1; 204 for (int i = 0; i < value_input_count; ++i) { 205 inputs[i] = graph()->start(); 206 } 207 Node* const merge = graph()->NewNode(common()->Merge(value_input_count), 208 value_input_count, inputs); 209 for (int i = 0; i < value_input_count; ++i) { 210 inputs[i] = input; 211 } 212 inputs[value_input_count] = merge; 213 StrictMock<MockAdvancedReducerEditor> editor; 214 EXPECT_CALL(editor, Revisit(merge)); 215 Reduction r = 216 Reduce(&editor, graph()->NewNode(common()->EffectPhi(value_input_count), 217 input_count, inputs)); 218 ASSERT_TRUE(r.Changed()); 219 EXPECT_EQ(input, r.replacement()); 220 } 221 } 222 223 224 TEST_F(CommonOperatorReducerTest, EffectPhiWithLoop) { 225 Node* const e0 = graph()->NewNode(&kOp0); 226 Node* const loop = 227 graph()->NewNode(common()->Loop(2), graph()->start(), graph()->start()); 228 loop->ReplaceInput(1, loop); 229 Node* const ephi = graph()->NewNode(common()->EffectPhi(2), e0, e0, loop); 230 ephi->ReplaceInput(1, ephi); 231 StrictMock<MockAdvancedReducerEditor> editor; 232 EXPECT_CALL(editor, Revisit(loop)); 233 Reduction const r = Reduce(&editor, ephi); 234 ASSERT_TRUE(r.Changed()); 235 EXPECT_EQ(e0, r.replacement()); 236 } 237 238 239 // ----------------------------------------------------------------------------- 240 // Phi 241 242 243 TEST_F(CommonOperatorReducerTest, PhiWithMerge) { 244 const int kMaxInputs = 64; 245 Node* inputs[kMaxInputs]; 246 Node* const input = graph()->NewNode(&kOp0); 247 TRACED_FORRANGE(int, input_count, 2, kMaxInputs - 1) { 248 int const value_input_count = input_count - 1; 249 TRACED_FOREACH(MachineRepresentation, rep, kMachineRepresentations) { 250 for (int i = 0; i < value_input_count; ++i) { 251 inputs[i] = graph()->start(); 252 } 253 Node* const merge = graph()->NewNode(common()->Merge(value_input_count), 254 value_input_count, inputs); 255 for (int i = 0; i < value_input_count; ++i) { 256 inputs[i] = input; 257 } 258 inputs[value_input_count] = merge; 259 StrictMock<MockAdvancedReducerEditor> editor; 260 EXPECT_CALL(editor, Revisit(merge)); 261 Reduction r = Reduce( 262 &editor, graph()->NewNode(common()->Phi(rep, value_input_count), 263 input_count, inputs)); 264 ASSERT_TRUE(r.Changed()); 265 EXPECT_EQ(input, r.replacement()); 266 } 267 } 268 } 269 270 271 TEST_F(CommonOperatorReducerTest, PhiWithLoop) { 272 Node* const p0 = Parameter(0); 273 Node* const loop = 274 graph()->NewNode(common()->Loop(2), graph()->start(), graph()->start()); 275 loop->ReplaceInput(1, loop); 276 Node* const phi = graph()->NewNode( 277 common()->Phi(MachineRepresentation::kTagged, 2), p0, p0, loop); 278 phi->ReplaceInput(1, phi); 279 StrictMock<MockAdvancedReducerEditor> editor; 280 EXPECT_CALL(editor, Revisit(loop)); 281 Reduction const r = Reduce(&editor, phi); 282 ASSERT_TRUE(r.Changed()); 283 EXPECT_EQ(p0, r.replacement()); 284 } 285 286 287 TEST_F(CommonOperatorReducerTest, PhiToFloat32Abs) { 288 Node* p0 = Parameter(0); 289 Node* c0 = Float32Constant(0.0); 290 Node* check = graph()->NewNode(machine()->Float32LessThan(), c0, p0); 291 Node* branch = graph()->NewNode(common()->Branch(), check, graph()->start()); 292 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); 293 Node* vtrue = p0; 294 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); 295 Node* vfalse = graph()->NewNode(machine()->Float32Sub(), c0, p0); 296 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); 297 Node* phi = graph()->NewNode( 298 common()->Phi(MachineRepresentation::kFloat32, 2), vtrue, vfalse, merge); 299 StrictMock<MockAdvancedReducerEditor> editor; 300 EXPECT_CALL(editor, Revisit(merge)); 301 Reduction r = Reduce(&editor, phi); 302 ASSERT_TRUE(r.Changed()); 303 EXPECT_THAT(r.replacement(), IsFloat32Abs(p0)); 304 } 305 306 307 TEST_F(CommonOperatorReducerTest, PhiToFloat64Abs) { 308 Node* p0 = Parameter(0); 309 Node* c0 = Float64Constant(0.0); 310 Node* check = graph()->NewNode(machine()->Float64LessThan(), c0, p0); 311 Node* branch = graph()->NewNode(common()->Branch(), check, graph()->start()); 312 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); 313 Node* vtrue = p0; 314 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); 315 Node* vfalse = graph()->NewNode(machine()->Float64Sub(), c0, p0); 316 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); 317 Node* phi = graph()->NewNode( 318 common()->Phi(MachineRepresentation::kFloat64, 2), vtrue, vfalse, merge); 319 StrictMock<MockAdvancedReducerEditor> editor; 320 EXPECT_CALL(editor, Revisit(merge)); 321 Reduction r = Reduce(&editor, phi); 322 ASSERT_TRUE(r.Changed()); 323 EXPECT_THAT(r.replacement(), IsFloat64Abs(p0)); 324 } 325 326 327 TEST_F(CommonOperatorReducerTest, PhiToFloat32Max) { 328 Node* p0 = Parameter(0); 329 Node* p1 = Parameter(1); 330 Node* check = graph()->NewNode(machine()->Float32LessThan(), p0, p1); 331 Node* branch = graph()->NewNode(common()->Branch(), check, graph()->start()); 332 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); 333 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); 334 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); 335 Node* phi = graph()->NewNode( 336 common()->Phi(MachineRepresentation::kFloat32, 2), p1, p0, merge); 337 StrictMock<MockAdvancedReducerEditor> editor; 338 EXPECT_CALL(editor, Revisit(merge)); 339 Reduction r = Reduce(&editor, phi, MachineOperatorBuilder::kFloat32Max); 340 ASSERT_TRUE(r.Changed()); 341 EXPECT_THAT(r.replacement(), IsFloat32Max(p1, p0)); 342 } 343 344 345 TEST_F(CommonOperatorReducerTest, PhiToFloat64Max) { 346 Node* p0 = Parameter(0); 347 Node* p1 = Parameter(1); 348 Node* check = graph()->NewNode(machine()->Float64LessThan(), p0, p1); 349 Node* branch = graph()->NewNode(common()->Branch(), check, graph()->start()); 350 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); 351 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); 352 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); 353 Node* phi = graph()->NewNode( 354 common()->Phi(MachineRepresentation::kFloat64, 2), p1, p0, merge); 355 StrictMock<MockAdvancedReducerEditor> editor; 356 EXPECT_CALL(editor, Revisit(merge)); 357 Reduction r = Reduce(&editor, phi, MachineOperatorBuilder::kFloat64Max); 358 ASSERT_TRUE(r.Changed()); 359 EXPECT_THAT(r.replacement(), IsFloat64Max(p1, p0)); 360 } 361 362 363 TEST_F(CommonOperatorReducerTest, PhiToFloat32Min) { 364 Node* p0 = Parameter(0); 365 Node* p1 = Parameter(1); 366 Node* check = graph()->NewNode(machine()->Float32LessThan(), p0, p1); 367 Node* branch = graph()->NewNode(common()->Branch(), check, graph()->start()); 368 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); 369 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); 370 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); 371 Node* phi = graph()->NewNode( 372 common()->Phi(MachineRepresentation::kFloat32, 2), p0, p1, merge); 373 StrictMock<MockAdvancedReducerEditor> editor; 374 EXPECT_CALL(editor, Revisit(merge)); 375 Reduction r = Reduce(&editor, phi, MachineOperatorBuilder::kFloat32Min); 376 ASSERT_TRUE(r.Changed()); 377 EXPECT_THAT(r.replacement(), IsFloat32Min(p0, p1)); 378 } 379 380 381 TEST_F(CommonOperatorReducerTest, PhiToFloat64Min) { 382 Node* p0 = Parameter(0); 383 Node* p1 = Parameter(1); 384 Node* check = graph()->NewNode(machine()->Float64LessThan(), p0, p1); 385 Node* branch = graph()->NewNode(common()->Branch(), check, graph()->start()); 386 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); 387 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); 388 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); 389 Node* phi = graph()->NewNode( 390 common()->Phi(MachineRepresentation::kFloat64, 2), p0, p1, merge); 391 StrictMock<MockAdvancedReducerEditor> editor; 392 EXPECT_CALL(editor, Revisit(merge)); 393 Reduction r = Reduce(&editor, phi, MachineOperatorBuilder::kFloat64Min); 394 ASSERT_TRUE(r.Changed()); 395 EXPECT_THAT(r.replacement(), IsFloat64Min(p0, p1)); 396 } 397 398 399 // ----------------------------------------------------------------------------- 400 // Return 401 402 403 TEST_F(CommonOperatorReducerTest, ReturnWithPhiAndEffectPhiAndMerge) { 404 Node* cond = Parameter(2); 405 Node* branch = graph()->NewNode(common()->Branch(), cond, graph()->start()); 406 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); 407 Node* etrue = graph()->start(); 408 Node* vtrue = Parameter(0); 409 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); 410 Node* efalse = graph()->start(); 411 Node* vfalse = Parameter(1); 412 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); 413 Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge); 414 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), 415 vtrue, vfalse, merge); 416 Node* ret = graph()->NewNode(common()->Return(), phi, ephi, merge); 417 graph()->SetEnd(graph()->NewNode(common()->End(1), ret)); 418 StrictMock<MockAdvancedReducerEditor> editor; 419 EXPECT_CALL(editor, Replace(merge, IsDead())); 420 Reduction const r = Reduce(&editor, ret); 421 ASSERT_TRUE(r.Changed()); 422 EXPECT_THAT(r.replacement(), IsDead()); 423 EXPECT_THAT(graph()->end(), IsEnd(ret, IsReturn(vtrue, etrue, if_true), 424 IsReturn(vfalse, efalse, if_false))); 425 } 426 427 428 // ----------------------------------------------------------------------------- 429 // Select 430 431 432 TEST_F(CommonOperatorReducerTest, SelectWithSameThenAndElse) { 433 Node* const input = graph()->NewNode(&kOp0); 434 TRACED_FOREACH(BranchHint, hint, kBranchHints) { 435 TRACED_FOREACH(MachineRepresentation, rep, kMachineRepresentations) { 436 Reduction r = Reduce( 437 graph()->NewNode(common()->Select(rep, hint), input, input, input)); 438 ASSERT_TRUE(r.Changed()); 439 EXPECT_EQ(input, r.replacement()); 440 } 441 } 442 } 443 444 445 TEST_F(CommonOperatorReducerTest, SelectWithInt32ZeroConstant) { 446 Node* p0 = Parameter(0); 447 Node* p1 = Parameter(1); 448 Node* select = 449 graph()->NewNode(common()->Select(MachineRepresentation::kTagged), 450 Int32Constant(0), p0, p1); 451 Reduction r = Reduce(select); 452 ASSERT_TRUE(r.Changed()); 453 EXPECT_EQ(p1, r.replacement()); 454 } 455 456 457 TEST_F(CommonOperatorReducerTest, SelectWithInt32OneConstant) { 458 Node* p0 = Parameter(0); 459 Node* p1 = Parameter(1); 460 Node* select = 461 graph()->NewNode(common()->Select(MachineRepresentation::kTagged), 462 Int32Constant(1), p0, p1); 463 Reduction r = Reduce(select); 464 ASSERT_TRUE(r.Changed()); 465 EXPECT_EQ(p0, r.replacement()); 466 } 467 468 469 TEST_F(CommonOperatorReducerTest, SelectWithFalseConstant) { 470 Node* p0 = Parameter(0); 471 Node* p1 = Parameter(1); 472 Node* select = 473 graph()->NewNode(common()->Select(MachineRepresentation::kTagged), 474 FalseConstant(), p0, p1); 475 Reduction r = Reduce(select); 476 ASSERT_TRUE(r.Changed()); 477 EXPECT_EQ(p1, r.replacement()); 478 } 479 480 481 TEST_F(CommonOperatorReducerTest, SelectWithTrueConstant) { 482 Node* p0 = Parameter(0); 483 Node* p1 = Parameter(1); 484 Node* select = graph()->NewNode( 485 common()->Select(MachineRepresentation::kTagged), TrueConstant(), p0, p1); 486 Reduction r = Reduce(select); 487 ASSERT_TRUE(r.Changed()); 488 EXPECT_EQ(p0, r.replacement()); 489 } 490 491 492 TEST_F(CommonOperatorReducerTest, SelectToFloat32Abs) { 493 Node* p0 = Parameter(0); 494 Node* c0 = Float32Constant(0.0); 495 Node* check = graph()->NewNode(machine()->Float32LessThan(), c0, p0); 496 Node* select = 497 graph()->NewNode(common()->Select(MachineRepresentation::kFloat32), check, 498 p0, graph()->NewNode(machine()->Float32Sub(), c0, p0)); 499 Reduction r = Reduce(select); 500 ASSERT_TRUE(r.Changed()); 501 EXPECT_THAT(r.replacement(), IsFloat32Abs(p0)); 502 } 503 504 505 TEST_F(CommonOperatorReducerTest, SelectToFloat64Abs) { 506 Node* p0 = Parameter(0); 507 Node* c0 = Float64Constant(0.0); 508 Node* check = graph()->NewNode(machine()->Float64LessThan(), c0, p0); 509 Node* select = 510 graph()->NewNode(common()->Select(MachineRepresentation::kFloat64), check, 511 p0, graph()->NewNode(machine()->Float64Sub(), c0, p0)); 512 Reduction r = Reduce(select); 513 ASSERT_TRUE(r.Changed()); 514 EXPECT_THAT(r.replacement(), IsFloat64Abs(p0)); 515 } 516 517 518 TEST_F(CommonOperatorReducerTest, SelectToFloat32Max) { 519 Node* p0 = Parameter(0); 520 Node* p1 = Parameter(1); 521 Node* check = graph()->NewNode(machine()->Float32LessThan(), p0, p1); 522 Node* select = graph()->NewNode( 523 common()->Select(MachineRepresentation::kFloat32), check, p1, p0); 524 Reduction r = Reduce(select, MachineOperatorBuilder::kFloat32Max); 525 ASSERT_TRUE(r.Changed()); 526 EXPECT_THAT(r.replacement(), IsFloat32Max(p1, p0)); 527 } 528 529 530 TEST_F(CommonOperatorReducerTest, SelectToFloat64Max) { 531 Node* p0 = Parameter(0); 532 Node* p1 = Parameter(1); 533 Node* check = graph()->NewNode(machine()->Float64LessThan(), p0, p1); 534 Node* select = graph()->NewNode( 535 common()->Select(MachineRepresentation::kFloat64), check, p1, p0); 536 Reduction r = Reduce(select, MachineOperatorBuilder::kFloat64Max); 537 ASSERT_TRUE(r.Changed()); 538 EXPECT_THAT(r.replacement(), IsFloat64Max(p1, p0)); 539 } 540 541 542 TEST_F(CommonOperatorReducerTest, SelectToFloat32Min) { 543 Node* p0 = Parameter(0); 544 Node* p1 = Parameter(1); 545 Node* check = graph()->NewNode(machine()->Float32LessThan(), p0, p1); 546 Node* select = graph()->NewNode( 547 common()->Select(MachineRepresentation::kFloat32), check, p0, p1); 548 Reduction r = Reduce(select, MachineOperatorBuilder::kFloat32Min); 549 ASSERT_TRUE(r.Changed()); 550 EXPECT_THAT(r.replacement(), IsFloat32Min(p0, p1)); 551 } 552 553 554 TEST_F(CommonOperatorReducerTest, SelectToFloat64Min) { 555 Node* p0 = Parameter(0); 556 Node* p1 = Parameter(1); 557 Node* check = graph()->NewNode(machine()->Float64LessThan(), p0, p1); 558 Node* select = graph()->NewNode( 559 common()->Select(MachineRepresentation::kFloat64), check, p0, p1); 560 Reduction r = Reduce(select, MachineOperatorBuilder::kFloat64Min); 561 ASSERT_TRUE(r.Changed()); 562 EXPECT_THAT(r.replacement(), IsFloat64Min(p0, p1)); 563 } 564 565 } // namespace compiler 566 } // namespace internal 567 } // namespace v8 568