| 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/v8.h" | 5 #include "src/v8.h" |
| 6 #include "test/cctest/cctest.h" | 6 #include "test/cctest/cctest.h" |
| 7 | 7 |
| 8 #include "src/base/bits.h" | 8 #include "src/base/bits.h" |
| 9 #include "src/compiler/all-nodes.h" | 9 #include "src/compiler/all-nodes.h" |
| 10 #include "src/compiler/common-operator.h" | 10 #include "src/compiler/common-operator.h" |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 for (Edge edge : node->input_edges()) { | 134 for (Edge edge : node->input_edges()) { |
| 135 if (edge.to() == self) node->ReplaceInput(edge.index(), node); | 135 if (edge.to() == self) node->ReplaceInput(edge.index(), node); |
| 136 } | 136 } |
| 137 return node; | 137 return node; |
| 138 } | 138 } |
| 139 | 139 |
| 140 const Operator* op(int count, bool effect) { | 140 const Operator* op(int count, bool effect) { |
| 141 return effect ? common.EffectPhi(count) : common.Phi(kMachAnyTagged, count); | 141 return effect ? common.EffectPhi(count) : common.Phi(kMachAnyTagged, count); |
| 142 } | 142 } |
| 143 | 143 |
| 144 void Trim() { ControlReducer::TrimGraph(main_zone(), &jsgraph); } | |
| 145 | |
| 146 void ReduceGraph() { ControlReducer::ReduceGraph(main_zone(), &jsgraph); } | 144 void ReduceGraph() { ControlReducer::ReduceGraph(main_zone(), &jsgraph); } |
| 147 | 145 |
| 148 // Checks one-step reduction of a phi. | 146 // Checks one-step reduction of a phi. |
| 149 void ReducePhi(Node* expect, Node* phi) { | 147 void ReducePhi(Node* expect, Node* phi) { |
| 150 Node* result = ControlReducer::ReducePhiForTesting(&jsgraph, phi); | 148 Node* result = ControlReducer::ReducePhiForTesting(&jsgraph, phi); |
| 151 CHECK_EQ(expect, result); | 149 CHECK_EQ(expect, result); |
| 152 ReducePhiIterative(expect, phi); // iterative should give the same result. | 150 ReducePhiIterative(expect, phi); // iterative should give the same result. |
| 153 } | 151 } |
| 154 | 152 |
| 155 // Checks one-step reduction of a phi. | 153 // Checks one-step reduction of a phi. |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 304 CHECK_EQ(3, d.phi->InputCount()); | 302 CHECK_EQ(3, d.phi->InputCount()); |
| 305 CHECK_EQ(d.merge, d.phi->InputAt(2)); | 303 CHECK_EQ(d.merge, d.phi->InputAt(2)); |
| 306 } else { | 304 } else { |
| 307 Check(d.phi); | 305 Check(d.phi); |
| 308 } | 306 } |
| 309 } | 307 } |
| 310 } | 308 } |
| 311 }; | 309 }; |
| 312 | 310 |
| 313 | 311 |
| 314 TEST(Trim1_live) { | |
| 315 ControlReducerTester T; | |
| 316 CHECK(IsUsedBy(T.start, T.p0)); | |
| 317 T.graph.SetEnd(T.p0); | |
| 318 T.Trim(); | |
| 319 CHECK(IsUsedBy(T.start, T.p0)); | |
| 320 CheckInputs(T.p0, T.start); | |
| 321 } | |
| 322 | |
| 323 | |
| 324 TEST(Trim1_dead) { | |
| 325 ControlReducerTester T; | |
| 326 CHECK(IsUsedBy(T.start, T.p0)); | |
| 327 T.Trim(); | |
| 328 CHECK(!IsUsedBy(T.start, T.p0)); | |
| 329 CHECK(!T.p0->InputAt(0)); | |
| 330 } | |
| 331 | |
| 332 | |
| 333 TEST(Trim2_live) { | |
| 334 ControlReducerTester T; | |
| 335 Node* phi = | |
| 336 T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, T.start); | |
| 337 CHECK(IsUsedBy(T.one, phi)); | |
| 338 CHECK(IsUsedBy(T.half, phi)); | |
| 339 CHECK(IsUsedBy(T.start, phi)); | |
| 340 T.graph.SetEnd(phi); | |
| 341 T.Trim(); | |
| 342 CHECK(IsUsedBy(T.one, phi)); | |
| 343 CHECK(IsUsedBy(T.half, phi)); | |
| 344 CHECK(IsUsedBy(T.start, phi)); | |
| 345 CheckInputs(phi, T.one, T.half, T.start); | |
| 346 } | |
| 347 | |
| 348 | |
| 349 TEST(Trim2_dead) { | |
| 350 ControlReducerTester T; | |
| 351 Node* phi = | |
| 352 T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, T.start); | |
| 353 CHECK(IsUsedBy(T.one, phi)); | |
| 354 CHECK(IsUsedBy(T.half, phi)); | |
| 355 CHECK(IsUsedBy(T.start, phi)); | |
| 356 T.Trim(); | |
| 357 CHECK(!IsUsedBy(T.one, phi)); | |
| 358 CHECK(!IsUsedBy(T.half, phi)); | |
| 359 CHECK(!IsUsedBy(T.start, phi)); | |
| 360 CHECK(!phi->InputAt(0)); | |
| 361 CHECK(!phi->InputAt(1)); | |
| 362 CHECK(!phi->InputAt(2)); | |
| 363 } | |
| 364 | |
| 365 | |
| 366 TEST(Trim_chain1) { | |
| 367 ControlReducerTester T; | |
| 368 const int kDepth = 15; | |
| 369 Node* live[kDepth]; | |
| 370 Node* dead[kDepth]; | |
| 371 Node* end = T.start; | |
| 372 for (int i = 0; i < kDepth; i++) { | |
| 373 live[i] = end = T.graph.NewNode(T.common.Merge(1), end); | |
| 374 dead[i] = T.graph.NewNode(T.common.Merge(1), end); | |
| 375 } | |
| 376 // end -> live[last] -> live[last-1] -> ... -> start | |
| 377 // dead[last] ^ dead[last-1] ^ ... ^ | |
| 378 T.graph.SetEnd(end); | |
| 379 T.Trim(); | |
| 380 for (int i = 0; i < kDepth; i++) { | |
| 381 CHECK(!IsUsedBy(live[i], dead[i])); | |
| 382 CHECK(!dead[i]->InputAt(0)); | |
| 383 CHECK_EQ(i == 0 ? T.start : live[i - 1], live[i]->InputAt(0)); | |
| 384 } | |
| 385 } | |
| 386 | |
| 387 | |
| 388 TEST(Trim_chain2) { | |
| 389 ControlReducerTester T; | |
| 390 const int kDepth = 15; | |
| 391 Node* live[kDepth]; | |
| 392 Node* dead[kDepth]; | |
| 393 Node* l = T.start; | |
| 394 Node* d = T.start; | |
| 395 for (int i = 0; i < kDepth; i++) { | |
| 396 live[i] = l = T.graph.NewNode(T.common.Merge(1), l); | |
| 397 dead[i] = d = T.graph.NewNode(T.common.Merge(1), d); | |
| 398 } | |
| 399 // end -> live[last] -> live[last-1] -> ... -> start | |
| 400 // dead[last] -> dead[last-1] -> ... -> start | |
| 401 T.graph.SetEnd(l); | |
| 402 T.Trim(); | |
| 403 CHECK(!IsUsedBy(T.start, dead[0])); | |
| 404 for (int i = 0; i < kDepth; i++) { | |
| 405 CHECK_EQ(i == 0 ? NULL : dead[i - 1], dead[i]->InputAt(0)); | |
| 406 CHECK_EQ(i == 0 ? T.start : live[i - 1], live[i]->InputAt(0)); | |
| 407 } | |
| 408 } | |
| 409 | |
| 410 | |
| 411 TEST(Trim_cycle1) { | |
| 412 ControlReducerTester T; | |
| 413 Node* loop = T.graph.NewNode(T.common.Loop(1), T.start, T.start); | |
| 414 loop->ReplaceInput(1, loop); | |
| 415 Node* end = T.graph.NewNode(T.common.End(1), loop); | |
| 416 T.graph.SetEnd(end); | |
| 417 | |
| 418 CHECK(IsUsedBy(T.start, loop)); | |
| 419 CHECK(IsUsedBy(loop, end)); | |
| 420 CHECK(IsUsedBy(loop, loop)); | |
| 421 | |
| 422 T.Trim(); | |
| 423 | |
| 424 // nothing should have happened to the loop itself. | |
| 425 CHECK(IsUsedBy(T.start, loop)); | |
| 426 CHECK(IsUsedBy(loop, end)); | |
| 427 CHECK(IsUsedBy(loop, loop)); | |
| 428 CheckInputs(loop, T.start, loop); | |
| 429 CheckInputs(end, loop); | |
| 430 } | |
| 431 | |
| 432 | |
| 433 TEST(Trim_cycle2) { | |
| 434 ControlReducerTester T; | |
| 435 Node* loop = T.graph.NewNode(T.common.Loop(2), T.start, T.start); | |
| 436 loop->ReplaceInput(1, loop); | |
| 437 Node* end = T.graph.NewNode(T.common.End(1), loop); | |
| 438 Node* phi = | |
| 439 T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, loop); | |
| 440 T.graph.SetEnd(end); | |
| 441 | |
| 442 CHECK(IsUsedBy(T.start, loop)); | |
| 443 CHECK(IsUsedBy(loop, end)); | |
| 444 CHECK(IsUsedBy(loop, loop)); | |
| 445 CHECK(IsUsedBy(loop, phi)); | |
| 446 CHECK(IsUsedBy(T.one, phi)); | |
| 447 CHECK(IsUsedBy(T.half, phi)); | |
| 448 | |
| 449 T.Trim(); | |
| 450 | |
| 451 // nothing should have happened to the loop itself. | |
| 452 CHECK(IsUsedBy(T.start, loop)); | |
| 453 CHECK(IsUsedBy(loop, end)); | |
| 454 CHECK(IsUsedBy(loop, loop)); | |
| 455 CheckInputs(loop, T.start, loop); | |
| 456 CheckInputs(end, loop); | |
| 457 | |
| 458 // phi should have been trimmed away. | |
| 459 CHECK(!IsUsedBy(loop, phi)); | |
| 460 CHECK(!IsUsedBy(T.one, phi)); | |
| 461 CHECK(!IsUsedBy(T.half, phi)); | |
| 462 CHECK(!phi->InputAt(0)); | |
| 463 CHECK(!phi->InputAt(1)); | |
| 464 CHECK(!phi->InputAt(2)); | |
| 465 } | |
| 466 | |
| 467 | |
| 468 void CheckTrimConstant(ControlReducerTester* T, Node* k) { | |
| 469 Node* phi = T->graph.NewNode(T->common.Phi(kMachInt32, 1), k, T->start); | |
| 470 CHECK(IsUsedBy(k, phi)); | |
| 471 T->Trim(); | |
| 472 CHECK(!IsUsedBy(k, phi)); | |
| 473 CHECK(!phi->InputAt(0)); | |
| 474 CHECK(!phi->InputAt(1)); | |
| 475 } | |
| 476 | |
| 477 | |
| 478 TEST(Trim_constants) { | |
| 479 ControlReducerTester T; | |
| 480 int32_t int32_constants[] = { | |
| 481 0, -1, -2, 2, 2, 3, 3, 4, 4, 5, 5, 4, 5, 6, 6, 7, 8, 7, 8, 9, | |
| 482 0, -11, -12, 12, 12, 13, 13, 14, 14, 15, 15, 14, 15, 6, 6, 7, 8, 7, 8, 9}; | |
| 483 | |
| 484 for (size_t i = 0; i < arraysize(int32_constants); i++) { | |
| 485 CheckTrimConstant(&T, T.jsgraph.Int32Constant(int32_constants[i])); | |
| 486 CheckTrimConstant(&T, T.jsgraph.Float64Constant(int32_constants[i])); | |
| 487 CheckTrimConstant(&T, T.jsgraph.Constant(int32_constants[i])); | |
| 488 } | |
| 489 | |
| 490 Node* other_constants[] = { | |
| 491 T.jsgraph.UndefinedConstant(), T.jsgraph.TheHoleConstant(), | |
| 492 T.jsgraph.TrueConstant(), T.jsgraph.FalseConstant(), | |
| 493 T.jsgraph.NullConstant(), T.jsgraph.ZeroConstant(), | |
| 494 T.jsgraph.OneConstant(), T.jsgraph.NaNConstant(), | |
| 495 T.jsgraph.Constant(21), T.jsgraph.Constant(22.2)}; | |
| 496 | |
| 497 for (size_t i = 0; i < arraysize(other_constants); i++) { | |
| 498 CheckTrimConstant(&T, other_constants[i]); | |
| 499 } | |
| 500 } | |
| 501 | |
| 502 | |
| 503 TEST(Trim_EmptyFrameState1) { | |
| 504 ControlReducerTester T; | |
| 505 | |
| 506 Node* node = T.jsgraph.EmptyFrameState(); | |
| 507 T.Trim(); | |
| 508 | |
| 509 for (Node* input : node->inputs()) { | |
| 510 CHECK_NOT_NULL(input); | |
| 511 } | |
| 512 } | |
| 513 | |
| 514 | |
| 515 TEST(Trim_EmptyFrameState2) { | |
| 516 ControlReducerTester T; | |
| 517 CheckTrimConstant(&T, T.jsgraph.EmptyFrameState()); | |
| 518 } | |
| 519 | |
| 520 | |
| 521 TEST(CReducePhi1) { | 312 TEST(CReducePhi1) { |
| 522 ControlReducerTester R; | 313 ControlReducerTester R; |
| 523 | 314 |
| 524 R.ReducePhi(R.leaf[0], R.Phi(R.leaf[0])); | 315 R.ReducePhi(R.leaf[0], R.Phi(R.leaf[0])); |
| 525 R.ReducePhi(R.leaf[1], R.Phi(R.leaf[1])); | 316 R.ReducePhi(R.leaf[1], R.Phi(R.leaf[1])); |
| 526 R.ReducePhi(R.leaf[2], R.Phi(R.leaf[2])); | 317 R.ReducePhi(R.leaf[2], R.Phi(R.leaf[2])); |
| 527 R.ReducePhi(R.leaf[3], R.Phi(R.leaf[3])); | 318 R.ReducePhi(R.leaf[3], R.Phi(R.leaf[3])); |
| 528 } | 319 } |
| 529 | 320 |
| 530 | 321 |
| (...skipping 1084 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1615 | 1406 |
| 1616 R.ReduceGraph(); // d1 gets folded true. | 1407 R.ReduceGraph(); // d1 gets folded true. |
| 1617 | 1408 |
| 1618 CheckInputs(ret, y2, R.start, R.start); | 1409 CheckInputs(ret, y2, R.start, R.start); |
| 1619 | 1410 |
| 1620 DeadChecker dead(&R.graph); | 1411 DeadChecker dead(&R.graph); |
| 1621 dead.Check(d1); | 1412 dead.Check(d1); |
| 1622 dead.Check(d2); | 1413 dead.Check(d2); |
| 1623 dead.Check(d3); | 1414 dead.Check(d3); |
| 1624 } | 1415 } |
| OLD | NEW |