Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(26)

Side by Side Diff: src/hydrogen-gvn.cc

Issue 149403003: A64: Synchronize with r19234. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen-gvn.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 GVNFlag changes_flag = HValue::ChangesFlagFromInt(i); 357 GVNFlag changes_flag = HValue::ChangesFlagFromInt(i);
358 if (flags.Contains(changes_flag)) { 358 if (flags.Contains(changes_flag)) {
359 if (data_[i] == NULL) count_++; 359 if (data_[i] == NULL) count_++;
360 data_[i] = instr; 360 data_[i] = instr;
361 } 361 }
362 } 362 }
363 } 363 }
364 364
365 365
366 HGlobalValueNumberingPhase::HGlobalValueNumberingPhase(HGraph* graph) 366 HGlobalValueNumberingPhase::HGlobalValueNumberingPhase(HGraph* graph)
367 : HPhase("H_Global value numbering", graph), 367 : HPhase("H_Global value numbering", graph),
368 removed_side_effects_(false), 368 removed_side_effects_(false),
369 block_side_effects_(graph->blocks()->length(), zone()), 369 block_side_effects_(graph->blocks()->length(), zone()),
370 loop_side_effects_(graph->blocks()->length(), zone()), 370 loop_side_effects_(graph->blocks()->length(), zone()),
371 visited_on_paths_(graph->blocks()->length(), zone()) { 371 visited_on_paths_(graph->blocks()->length(), zone()) {
372 ASSERT(!AllowHandleAllocation::IsAllowed()); 372 ASSERT(!AllowHandleAllocation::IsAllowed());
373 block_side_effects_.AddBlock(GVNFlagSet(), graph->blocks()->length(), 373 block_side_effects_.AddBlock(GVNFlagSet(), graph->blocks()->length(),
374 zone());
375 loop_side_effects_.AddBlock(GVNFlagSet(), graph->blocks()->length(),
376 zone()); 374 zone());
375 loop_side_effects_.AddBlock(GVNFlagSet(), graph->blocks()->length(),
376 zone());
377 }
378
379
380 void HGlobalValueNumberingPhase::Run() {
381 ASSERT(!removed_side_effects_);
382 for (int i = FLAG_gvn_iterations; i > 0; --i) {
383 // Compute the side effects.
384 ComputeBlockSideEffects();
385
386 // Perform loop invariant code motion if requested.
387 if (FLAG_loop_invariant_code_motion) LoopInvariantCodeMotion();
388
389 // Perform the actual value numbering.
390 AnalyzeGraph();
391
392 // Continue GVN if we removed any side effects.
393 if (!removed_side_effects_) break;
394 removed_side_effects_ = false;
395
396 // Clear all side effects.
397 ASSERT_EQ(block_side_effects_.length(), graph()->blocks()->length());
398 ASSERT_EQ(loop_side_effects_.length(), graph()->blocks()->length());
399 for (int i = 0; i < graph()->blocks()->length(); ++i) {
400 block_side_effects_[i].RemoveAll();
401 loop_side_effects_[i].RemoveAll();
402 }
403 visited_on_paths_.Clear();
377 } 404 }
378
379 void HGlobalValueNumberingPhase::Analyze() {
380 removed_side_effects_ = false;
381 ComputeBlockSideEffects();
382 if (FLAG_loop_invariant_code_motion) {
383 LoopInvariantCodeMotion();
384 }
385 AnalyzeGraph();
386 } 405 }
387 406
388 407
389 void HGlobalValueNumberingPhase::ComputeBlockSideEffects() { 408 void HGlobalValueNumberingPhase::ComputeBlockSideEffects() {
390 // The Analyze phase of GVN can be called multiple times. Clear loop side
391 // effects before computing them to erase the contents from previous Analyze
392 // passes.
393 for (int i = 0; i < loop_side_effects_.length(); ++i) {
394 loop_side_effects_[i].RemoveAll();
395 }
396 for (int i = graph()->blocks()->length() - 1; i >= 0; --i) { 409 for (int i = graph()->blocks()->length() - 1; i >= 0; --i) {
397 // Compute side effects for the block. 410 // Compute side effects for the block.
398 HBasicBlock* block = graph()->blocks()->at(i); 411 HBasicBlock* block = graph()->blocks()->at(i);
399 GVNFlagSet side_effects; 412 GVNFlagSet side_effects;
400 if (block->IsReachable() && !block->IsDeoptimizing()) { 413 if (block->IsReachable() && !block->IsDeoptimizing()) {
401 int id = block->block_id(); 414 int id = block->block_id();
402 for (HInstructionIterator it(block); !it.Done(); it.Advance()) { 415 for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
403 HInstruction* instr = it.Current(); 416 HInstruction* instr = it.Current();
404 side_effects.Add(instr->ChangesFlags()); 417 side_effects.Add(instr->ChangesFlags());
405 } 418 }
(...skipping 13 matching lines...) Expand all
419 loop_side_effects_[parent_block->block_id()].Add(side_effects); 432 loop_side_effects_[parent_block->block_id()].Add(side_effects);
420 with_parent = parent_block; 433 with_parent = parent_block;
421 } while (with_parent->HasParentLoopHeader()); 434 } while (with_parent->HasParentLoopHeader());
422 } 435 }
423 } 436 }
424 } 437 }
425 } 438 }
426 439
427 440
428 SmartArrayPointer<char> GetGVNFlagsString(GVNFlagSet flags) { 441 SmartArrayPointer<char> GetGVNFlagsString(GVNFlagSet flags) {
429 char underlying_buffer[kLastFlag * 128]; 442 char underlying_buffer[kNumberOfFlags * 128];
430 Vector<char> buffer(underlying_buffer, sizeof(underlying_buffer)); 443 Vector<char> buffer(underlying_buffer, sizeof(underlying_buffer));
431 #if DEBUG 444 #if DEBUG
432 int offset = 0; 445 int offset = 0;
433 const char* separator = ""; 446 const char* separator = "";
434 const char* comma = ", "; 447 const char* comma = ", ";
435 buffer[0] = 0; 448 buffer[0] = 0;
436 uint32_t set_depends_on = 0; 449 uint32_t set_depends_on = 0;
437 uint32_t set_changes = 0; 450 uint32_t set_changes = 0;
438 for (int bit = 0; bit < kLastFlag; ++bit) { 451 for (int bit = 0; bit < kNumberOfFlags; ++bit) {
439 if (flags.Contains(static_cast<GVNFlag>(bit))) { 452 if (flags.Contains(static_cast<GVNFlag>(bit))) {
440 if (bit % 2 == 0) { 453 if (bit % 2 == 0) {
441 set_changes++; 454 set_changes++;
442 } else { 455 } else {
443 set_depends_on++; 456 set_depends_on++;
444 } 457 }
445 } 458 }
446 } 459 }
447 bool positive_changes = set_changes < (kLastFlag / 2); 460 bool positive_changes = set_changes < (kNumberOfFlags / 2);
448 bool positive_depends_on = set_depends_on < (kLastFlag / 2); 461 bool positive_depends_on = set_depends_on < (kNumberOfFlags / 2);
449 if (set_changes > 0) { 462 if (set_changes > 0) {
450 if (positive_changes) { 463 if (positive_changes) {
451 offset += OS::SNPrintF(buffer + offset, "changes ["); 464 offset += OS::SNPrintF(buffer + offset, "changes [");
452 } else { 465 } else {
453 offset += OS::SNPrintF(buffer + offset, "changes all except ["); 466 offset += OS::SNPrintF(buffer + offset, "changes all except [");
454 } 467 }
455 for (int bit = 0; bit < kLastFlag; ++bit) { 468 for (int bit = 0; bit < kNumberOfFlags; ++bit) {
456 if (flags.Contains(static_cast<GVNFlag>(bit)) == positive_changes) { 469 if (flags.Contains(static_cast<GVNFlag>(bit)) == positive_changes) {
457 switch (static_cast<GVNFlag>(bit)) { 470 switch (static_cast<GVNFlag>(bit)) {
458 #define DECLARE_FLAG(type) \ 471 #define DECLARE_FLAG(type) \
459 case kChanges##type: \ 472 case kChanges##type: \
460 offset += OS::SNPrintF(buffer + offset, separator); \ 473 offset += OS::SNPrintF(buffer + offset, separator); \
461 offset += OS::SNPrintF(buffer + offset, #type); \ 474 offset += OS::SNPrintF(buffer + offset, #type); \
462 separator = comma; \ 475 separator = comma; \
463 break; 476 break;
464 GVN_TRACKED_FLAG_LIST(DECLARE_FLAG) 477 GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
465 GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG) 478 GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
466 #undef DECLARE_FLAG 479 #undef DECLARE_FLAG
467 default: 480 default:
468 break; 481 break;
469 } 482 }
470 } 483 }
471 } 484 }
472 offset += OS::SNPrintF(buffer + offset, "]"); 485 offset += OS::SNPrintF(buffer + offset, "]");
473 } 486 }
474 if (set_depends_on > 0) { 487 if (set_depends_on > 0) {
475 separator = ""; 488 separator = "";
476 if (set_changes > 0) { 489 if (set_changes > 0) {
477 offset += OS::SNPrintF(buffer + offset, ", "); 490 offset += OS::SNPrintF(buffer + offset, ", ");
478 } 491 }
479 if (positive_depends_on) { 492 if (positive_depends_on) {
480 offset += OS::SNPrintF(buffer + offset, "depends on ["); 493 offset += OS::SNPrintF(buffer + offset, "depends on [");
481 } else { 494 } else {
482 offset += OS::SNPrintF(buffer + offset, "depends on all except ["); 495 offset += OS::SNPrintF(buffer + offset, "depends on all except [");
483 } 496 }
484 for (int bit = 0; bit < kLastFlag; ++bit) { 497 for (int bit = 0; bit < kNumberOfFlags; ++bit) {
485 if (flags.Contains(static_cast<GVNFlag>(bit)) == positive_depends_on) { 498 if (flags.Contains(static_cast<GVNFlag>(bit)) == positive_depends_on) {
486 switch (static_cast<GVNFlag>(bit)) { 499 switch (static_cast<GVNFlag>(bit)) {
487 #define DECLARE_FLAG(type) \ 500 #define DECLARE_FLAG(type) \
488 case kDependsOn##type: \ 501 case kDependsOn##type: \
489 offset += OS::SNPrintF(buffer + offset, separator); \ 502 offset += OS::SNPrintF(buffer + offset, separator); \
490 offset += OS::SNPrintF(buffer + offset, #type); \ 503 offset += OS::SNPrintF(buffer + offset, #type); \
491 separator = comma; \ 504 separator = comma; \
492 break; 505 break;
493 GVN_TRACKED_FLAG_LIST(DECLARE_FLAG) 506 GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
494 GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG) 507 GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
(...skipping 20 matching lines...) Expand all
515 TRACE_GVN_1("Using optimistic loop invariant code motion: %s\n", 528 TRACE_GVN_1("Using optimistic loop invariant code motion: %s\n",
516 graph()->use_optimistic_licm() ? "yes" : "no"); 529 graph()->use_optimistic_licm() ? "yes" : "no");
517 for (int i = graph()->blocks()->length() - 1; i >= 0; --i) { 530 for (int i = graph()->blocks()->length() - 1; i >= 0; --i) {
518 HBasicBlock* block = graph()->blocks()->at(i); 531 HBasicBlock* block = graph()->blocks()->at(i);
519 if (block->IsLoopHeader()) { 532 if (block->IsLoopHeader()) {
520 GVNFlagSet side_effects = loop_side_effects_[block->block_id()]; 533 GVNFlagSet side_effects = loop_side_effects_[block->block_id()];
521 TRACE_GVN_2("Try loop invariant motion for block B%d %s\n", 534 TRACE_GVN_2("Try loop invariant motion for block B%d %s\n",
522 block->block_id(), 535 block->block_id(),
523 GetGVNFlagsString(side_effects).get()); 536 GetGVNFlagsString(side_effects).get());
524 537
525 GVNFlagSet accumulated_first_time_depends;
526 GVNFlagSet accumulated_first_time_changes;
527 HBasicBlock* last = block->loop_information()->GetLastBackEdge(); 538 HBasicBlock* last = block->loop_information()->GetLastBackEdge();
528 for (int j = block->block_id(); j <= last->block_id(); ++j) { 539 for (int j = block->block_id(); j <= last->block_id(); ++j) {
529 ProcessLoopBlock(graph()->blocks()->at(j), block, side_effects, 540 ProcessLoopBlock(graph()->blocks()->at(j), block, side_effects);
530 &accumulated_first_time_depends,
531 &accumulated_first_time_changes);
532 } 541 }
533 } 542 }
534 } 543 }
535 } 544 }
536 545
537 546
538 void HGlobalValueNumberingPhase::ProcessLoopBlock( 547 void HGlobalValueNumberingPhase::ProcessLoopBlock(
539 HBasicBlock* block, 548 HBasicBlock* block,
540 HBasicBlock* loop_header, 549 HBasicBlock* loop_header,
541 GVNFlagSet loop_kills, 550 GVNFlagSet loop_kills) {
542 GVNFlagSet* first_time_depends,
543 GVNFlagSet* first_time_changes) {
544 HBasicBlock* pre_header = loop_header->predecessors()->at(0); 551 HBasicBlock* pre_header = loop_header->predecessors()->at(0);
545 GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills); 552 GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills);
546 TRACE_GVN_2("Loop invariant motion for B%d %s\n", 553 TRACE_GVN_2("Loop invariant motion for B%d %s\n",
547 block->block_id(), 554 block->block_id(),
548 GetGVNFlagsString(depends_flags).get()); 555 GetGVNFlagsString(depends_flags).get());
549 HInstruction* instr = block->first(); 556 HInstruction* instr = block->first();
550 while (instr != NULL) { 557 while (instr != NULL) {
551 HInstruction* next = instr->next(); 558 HInstruction* next = instr->next();
552 bool hoisted = false;
553 if (instr->CheckFlag(HValue::kUseGVN)) { 559 if (instr->CheckFlag(HValue::kUseGVN)) {
554 TRACE_GVN_4("Checking instruction %d (%s) %s. Loop %s\n", 560 TRACE_GVN_4("Checking instruction %d (%s) %s. Loop %s\n",
555 instr->id(), 561 instr->id(),
556 instr->Mnemonic(), 562 instr->Mnemonic(),
557 GetGVNFlagsString(instr->gvn_flags()).get(), 563 GetGVNFlagsString(instr->gvn_flags()).get(),
558 GetGVNFlagsString(loop_kills).get()); 564 GetGVNFlagsString(loop_kills).get());
559 bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags); 565 bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags);
560 if (can_hoist && !graph()->use_optimistic_licm()) { 566 if (can_hoist && !graph()->use_optimistic_licm()) {
561 can_hoist = block->IsLoopSuccessorDominator(); 567 can_hoist = block->IsLoopSuccessorDominator();
562 } 568 }
563 569
564 if (can_hoist) { 570 if (can_hoist) {
565 bool inputs_loop_invariant = true; 571 bool inputs_loop_invariant = true;
566 for (int i = 0; i < instr->OperandCount(); ++i) { 572 for (int i = 0; i < instr->OperandCount(); ++i) {
567 if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) { 573 if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) {
568 inputs_loop_invariant = false; 574 inputs_loop_invariant = false;
569 } 575 }
570 } 576 }
571 577
572 if (inputs_loop_invariant && ShouldMove(instr, loop_header)) { 578 if (inputs_loop_invariant && ShouldMove(instr, loop_header)) {
573 TRACE_GVN_2("Hoisting loop invariant instruction i%d to block B%d\n", 579 TRACE_GVN_2("Hoisting loop invariant instruction i%d to block B%d\n",
574 instr->id(), pre_header->block_id()); 580 instr->id(), pre_header->block_id());
575 // Move the instruction out of the loop. 581 // Move the instruction out of the loop.
576 instr->Unlink(); 582 instr->Unlink();
577 instr->InsertBefore(pre_header->end()); 583 instr->InsertBefore(pre_header->end());
578 if (instr->HasSideEffects()) removed_side_effects_ = true; 584 if (instr->HasSideEffects()) removed_side_effects_ = true;
579 hoisted = true;
580 } 585 }
581 } 586 }
582 } 587 }
583 if (!hoisted) {
584 // If an instruction is not hoisted, we have to account for its side
585 // effects when hoisting later HTransitionElementsKind instructions.
586 GVNFlagSet previous_depends = *first_time_depends;
587 GVNFlagSet previous_changes = *first_time_changes;
588 first_time_depends->Add(instr->DependsOnFlags());
589 first_time_changes->Add(instr->ChangesFlags());
590 if (!(previous_depends == *first_time_depends)) {
591 TRACE_GVN_1("Updated first-time accumulated %s\n",
592 GetGVNFlagsString(*first_time_depends).get());
593 }
594 if (!(previous_changes == *first_time_changes)) {
595 TRACE_GVN_1("Updated first-time accumulated %s\n",
596 GetGVNFlagsString(*first_time_changes).get());
597 }
598 }
599 instr = next; 588 instr = next;
600 } 589 }
601 } 590 }
602 591
603 592
604 bool HGlobalValueNumberingPhase::AllowCodeMotion() { 593 bool HGlobalValueNumberingPhase::AllowCodeMotion() {
605 return info()->IsStub() || info()->opt_count() + 1 < FLAG_max_opt_count; 594 return info()->IsStub() || info()->opt_count() + 1 < FLAG_max_opt_count;
606 } 595 }
607 596
608 597
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
784 GVNFlag changes_flag = HValue::ChangesFlagFromInt(i); 773 GVNFlag changes_flag = HValue::ChangesFlagFromInt(i);
785 GVNFlag depends_on_flag = HValue::DependsOnFlagFromInt(i); 774 GVNFlag depends_on_flag = HValue::DependsOnFlagFromInt(i);
786 if (instr->DependsOnFlags().Contains(depends_on_flag) && 775 if (instr->DependsOnFlags().Contains(depends_on_flag) &&
787 (other != NULL)) { 776 (other != NULL)) {
788 TRACE_GVN_5("Side-effect #%d in %d (%s) is dominated by %d (%s)\n", 777 TRACE_GVN_5("Side-effect #%d in %d (%s) is dominated by %d (%s)\n",
789 i, 778 i,
790 instr->id(), 779 instr->id(),
791 instr->Mnemonic(), 780 instr->Mnemonic(),
792 other->id(), 781 other->id(),
793 other->Mnemonic()); 782 other->Mnemonic());
794 instr->HandleSideEffectDominator(changes_flag, other); 783 if (instr->HandleSideEffectDominator(changes_flag, other)) {
784 removed_side_effects_ = true;
785 }
795 } 786 }
796 } 787 }
797 } 788 }
798 // Instruction was unlinked during graph traversal. 789 // Instruction was unlinked during graph traversal.
799 if (!instr->IsLinked()) continue; 790 if (!instr->IsLinked()) continue;
800 791
801 GVNFlagSet flags = instr->ChangesFlags(); 792 GVNFlagSet flags = instr->ChangesFlags();
802 if (!flags.IsEmpty()) { 793 if (!flags.IsEmpty()) {
803 // Clear all instructions in the map that are affected by side effects. 794 // Clear all instructions in the map that are affected by side effects.
804 // Store instruction as the dominating one for tracked side effects. 795 // Store instruction as the dominating one for tracked side effects.
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
848 dominated); 839 dominated);
849 successor_map->Kill(side_effects_on_all_paths); 840 successor_map->Kill(side_effects_on_all_paths);
850 successor_dominators->Kill(side_effects_on_all_paths); 841 successor_dominators->Kill(side_effects_on_all_paths);
851 } 842 }
852 } 843 }
853 current = next; 844 current = next;
854 } 845 }
855 } 846 }
856 847
857 } } // namespace v8::internal 848 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen-gvn.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698