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

Side by Side Diff: src/lithium-allocator.cc

Issue 11575030: For the values defined in the loop and spilled outside sink spill store out of the loop down to loo… (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years 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
« src/lithium-allocator.h ('K') | « src/lithium-allocator.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 is_double_(false), 132 is_double_(false),
133 assigned_register_(kInvalidAssignment), 133 assigned_register_(kInvalidAssignment),
134 last_interval_(NULL), 134 last_interval_(NULL),
135 first_interval_(NULL), 135 first_interval_(NULL),
136 first_pos_(NULL), 136 first_pos_(NULL),
137 parent_(NULL), 137 parent_(NULL),
138 next_(NULL), 138 next_(NULL),
139 current_interval_(NULL), 139 current_interval_(NULL),
140 last_processed_use_(NULL), 140 last_processed_use_(NULL),
141 spill_operand_(new(zone) LOperand()), 141 spill_operand_(new(zone) LOperand()),
142 spill_start_index_(kMaxInt) { } 142 spill_start_index_(kMaxInt),
143 spill_source_(NULL) { }
143 144
144 145
145 void LiveRange::set_assigned_register(int reg, 146 void LiveRange::set_assigned_register(int reg,
146 RegisterKind register_kind, 147 RegisterKind register_kind,
147 Zone* zone) { 148 Zone* zone) {
148 ASSERT(!HasRegisterAssigned() && !IsSpilled()); 149 ASSERT(!HasRegisterAssigned() && !IsSpilled());
149 assigned_register_ = reg; 150 assigned_register_ = reg;
150 is_double_ = (register_kind == DOUBLE_REGISTERS); 151 is_double_ = (register_kind == DOUBLE_REGISTERS);
151 ConvertOperands(zone); 152 ConvertOperands(zone);
152 } 153 }
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 : zone_(graph->zone()), 535 : zone_(graph->zone()),
535 chunk_(NULL), 536 chunk_(NULL),
536 live_in_sets_(graph->blocks()->length(), zone_), 537 live_in_sets_(graph->blocks()->length(), zone_),
537 live_ranges_(num_values * 2, zone_), 538 live_ranges_(num_values * 2, zone_),
538 fixed_live_ranges_(NULL), 539 fixed_live_ranges_(NULL),
539 fixed_double_live_ranges_(NULL), 540 fixed_double_live_ranges_(NULL),
540 unhandled_live_ranges_(num_values * 2, zone_), 541 unhandled_live_ranges_(num_values * 2, zone_),
541 active_live_ranges_(8, zone_), 542 active_live_ranges_(8, zone_),
542 inactive_live_ranges_(8, zone_), 543 inactive_live_ranges_(8, zone_),
543 reusable_slots_(8, zone_), 544 reusable_slots_(8, zone_),
545 pending_spilled_(8, zone_),
544 next_virtual_register_(num_values), 546 next_virtual_register_(num_values),
545 first_artificial_register_(num_values), 547 first_artificial_register_(num_values),
546 mode_(GENERAL_REGISTERS), 548 mode_(GENERAL_REGISTERS),
547 num_registers_(-1), 549 num_registers_(-1),
548 graph_(graph), 550 graph_(graph),
549 has_osr_entry_(false), 551 has_osr_entry_(false),
550 allocation_ok_(true) { } 552 allocation_ok_(true) { }
551 553
552 554
553 void LAllocator::InitializeLivenessAnalysis() { 555 void LAllocator::InitializeLivenessAnalysis() {
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
791 if (temp->HasFixedPolicy()) { 793 if (temp->HasFixedPolicy()) {
792 AllocateFixed(temp, gap_index - 1, false); 794 AllocateFixed(temp, gap_index - 1, false);
793 } 795 }
794 } 796 }
795 } 797 }
796 798
797 // Handle fixed output operand. 799 // Handle fixed output operand.
798 if (first != NULL && first->Output() != NULL) { 800 if (first != NULL && first->Output() != NULL) {
799 LUnallocated* first_output = LUnallocated::cast(first->Output()); 801 LUnallocated* first_output = LUnallocated::cast(first->Output());
800 LiveRange* range = LiveRangeFor(first_output->virtual_register()); 802 LiveRange* range = LiveRangeFor(first_output->virtual_register());
801 bool assigned = false;
802 if (first_output->HasFixedPolicy()) { 803 if (first_output->HasFixedPolicy()) {
803 LUnallocated* output_copy = first_output->CopyUnconstrained(zone()); 804 LUnallocated* output_copy = first_output->CopyUnconstrained(zone());
804 bool is_tagged = HasTaggedValue(first_output->virtual_register()); 805 bool is_tagged = HasTaggedValue(first_output->virtual_register());
805 AllocateFixed(first_output, gap_index, is_tagged); 806 AllocateFixed(first_output, gap_index, is_tagged);
806 807
807 // This value is produced on the stack, we never need to spill it. 808 // This value is produced on the stack, we never need to spill it.
808 if (first_output->IsStackSlot()) { 809 if (first_output->IsStackSlot()) {
809 range->SetSpillOperand(first_output); 810 range->SetSpillOperand(first_output);
810 range->SetSpillStartIndex(gap_index - 1); 811 range->set_spill_start_index(gap_index - 1);
811 assigned = true;
812 } 812 }
813 chunk_->AddGapMove(gap_index, first_output, output_copy); 813 chunk_->AddGapMove(gap_index, first_output, output_copy);
814 } 814 }
815 815
816 if (!assigned) { 816 if (!range->HasAllocatedSpillOperand()) {
817 range->SetSpillStartIndex(gap_index); 817 // Instructions that are emitted at uses produce values multiple times
818 // from different spill sources. There is however no dominance relation
819 // between different occurrence of the same constant and thus we have to
820 // emit spill stores eagerly at all of them.
821 if (range->spill_source() != NULL) {
822 if (range->HasPendingSpillStore()) {
823 EmitSpillStore(range);
824 range->DisableSpillStoreSinking();
825 }
818 826
819 // This move to spill operand is not a real use. Liveness analysis 827 EmitSpillStore(gap_index, first_output, range->GetSpillOperand());
820 // and splitting of live ranges do not account for it. 828 } else {
821 // Thus it should be inserted to a lifetime position corresponding to 829 range->set_spill_start_index(gap_index);
822 // the instruction end. 830 range->set_spill_source(first_output);
823 LGap* gap = GapAt(gap_index); 831 }
824 LParallelMove* move = gap->GetOrCreateParallelMove(LGap::BEFORE, zone());
825 move->AddMove(first_output, range->GetSpillOperand(), zone());
826 } 832 }
827 } 833 }
828 834
829 // Handle fixed input operands of second instruction. 835 // Handle fixed input operands of second instruction.
830 if (second != NULL) { 836 if (second != NULL) {
831 for (UseIterator it(second); !it.Done(); it.Advance()) { 837 for (UseIterator it(second); !it.Done(); it.Advance()) {
832 LUnallocated* cur_input = LUnallocated::cast(it.Current()); 838 LUnallocated* cur_input = LUnallocated::cast(it.Current());
833 if (cur_input->HasFixedPolicy()) { 839 if (cur_input->HasFixedPolicy()) {
834 LUnallocated* input_copy = cur_input->CopyUnconstrained(zone()); 840 LUnallocated* input_copy = cur_input->CopyUnconstrained(zone());
835 bool is_tagged = HasTaggedValue(cur_input->virtual_register()); 841 bool is_tagged = HasTaggedValue(cur_input->virtual_register());
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
1047 if (branch->HasPointerMap()) { 1053 if (branch->HasPointerMap()) {
1048 if (phi->representation().IsTagged()) { 1054 if (phi->representation().IsTagged()) {
1049 branch->pointer_map()->RecordPointer(phi_operand, zone()); 1055 branch->pointer_map()->RecordPointer(phi_operand, zone());
1050 } else if (!phi->representation().IsDouble()) { 1056 } else if (!phi->representation().IsDouble()) {
1051 branch->pointer_map()->RecordUntagged(phi_operand, zone()); 1057 branch->pointer_map()->RecordUntagged(phi_operand, zone());
1052 } 1058 }
1053 } 1059 }
1054 } 1060 }
1055 1061
1056 LiveRange* live_range = LiveRangeFor(phi->id()); 1062 LiveRange* live_range = LiveRangeFor(phi->id());
1057 LLabel* label = chunk_->GetLabel(phi->block()->block_id()); 1063 live_range->set_spill_start_index(phi->block()->first_instruction_index());
1058 label->GetOrCreateParallelMove(LGap::START, zone())-> 1064 live_range->set_spill_source(phi_operand);
1059 AddMove(phi_operand, live_range->GetSpillOperand(), zone());
1060 live_range->SetSpillStartIndex(phi->block()->first_instruction_index());
1061 } 1065 }
1062 } 1066 }
1063 1067
1068
1069 void LAllocator::TrySinkSpillStoreTo(LiveRange* range, HBasicBlock* block) {
1070 LifetimePosition pos = LifetimePosition::FromInstructionIndex(
1071 block->first_instruction_index());
1072
1073 if (!range->Covers(pos)) {
1074 // For now we are limiting sinking to the case when initial live range
1075 // extends beyond the loop and covers the position to which we are trying
1076 // to sink the spill store.
1077 return;
1078 }
1079
1080 // Check that selected position dominates all spilled siblings.
1081 for (LiveRange* sibling = range; sibling != NULL; sibling = sibling->next()) {
1082 if (!sibling->IsSpilled()) {
1083 continue;
1084 }
1085
1086 if (pos.Value() > sibling->Start().Value()) {
1087 return;
1088 }
1089
1090 HBasicBlock* sibling_block = GetBlock(sibling->Start());
1091 if ((block != sibling_block) && !block->Dominates(sibling_block)) {
1092 return;
1093 }
1094 }
1095
1096 // Sink the spill store.
1097 range->set_spill_source(range->CreateAssignedOperand(zone()));
1098 range->set_spill_start_index(pos.InstructionIndex());
1099 }
1100
1101
1102 void LAllocator::SinkSpillStores() {
1103 for (int i = 0; i < pending_spilled_.length(); i++) {
1104 LiveRange* range = pending_spilled_[i];
1105
1106 HBasicBlock* range_block = GetBlock(range->Start());
1107
1108 HBasicBlock* loop_header = range_block->IsLoopHeader() ?
1109 range_block : range_block->parent_loop_header();
1110 ASSERT(loop_header != NULL);
1111
1112 HBasicBlock* block = loop_header->loop_information()->exit_block();
danno 2013/01/10 15:33:27 How about a loop here that tries to spill to the o
Vyacheslav Egorov (Google) 2013/01/25 13:49:17 Done.
1113 if (block != NULL) {
1114 TrySinkSpillStoreTo(range, block);
1115 }
1116
1117 EmitSpillStore(range);
1118 }
1119 }
1120
1064 1121
1065 bool LAllocator::Allocate(LChunk* chunk) { 1122 bool LAllocator::Allocate(LChunk* chunk) {
1066 ASSERT(chunk_ == NULL); 1123 ASSERT(chunk_ == NULL);
1067 chunk_ = static_cast<LPlatformChunk*>(chunk); 1124 chunk_ = static_cast<LPlatformChunk*>(chunk);
1068 MeetRegisterConstraints(); 1125 MeetRegisterConstraints();
1069 if (!AllocationOk()) return false; 1126 if (!AllocationOk()) return false;
1070 ResolvePhis(); 1127 ResolvePhis();
1071 BuildLiveRanges(); 1128 BuildLiveRanges();
1072 AllocateGeneralRegisters(); 1129 AllocateGeneralRegisters();
1073 if (!AllocationOk()) return false; 1130 if (!AllocationOk()) return false;
1074 AllocateDoubleRegisters(); 1131 AllocateDoubleRegisters();
1075 if (!AllocationOk()) return false; 1132 if (!AllocationOk()) return false;
1133
1134 // Sink pending spill stores down to loop exits. Should be done before
1135 // pointer maps are populated.
1136 SinkSpillStores();
1137
1076 PopulatePointerMaps(); 1138 PopulatePointerMaps();
1077 if (has_osr_entry_) ProcessOsrEntry(); 1139 if (has_osr_entry_) ProcessOsrEntry();
1078 ConnectRanges(); 1140 ConnectRanges();
1079 ResolveControlFlow(); 1141 ResolveControlFlow();
1080 return true; 1142 return true;
1081 } 1143 }
1082 1144
1083 1145
1084 void LAllocator::MeetRegisterConstraints() { 1146 void LAllocator::MeetRegisterConstraints() {
1085 HPhase phase("L_Register constraints", chunk_); 1147 HPhase phase("L_Register constraints", chunk_);
(...skipping 999 matching lines...) Expand 10 before | Expand all | Expand 10 after
2085 2147
2086 void LAllocator::Spill(LiveRange* range) { 2148 void LAllocator::Spill(LiveRange* range) {
2087 ASSERT(!range->IsSpilled()); 2149 ASSERT(!range->IsSpilled());
2088 TraceAlloc("Spilling live range %d\n", range->id()); 2150 TraceAlloc("Spilling live range %d\n", range->id());
2089 LiveRange* first = range->TopLevel(); 2151 LiveRange* first = range->TopLevel();
2090 2152
2091 if (!first->HasAllocatedSpillOperand()) { 2153 if (!first->HasAllocatedSpillOperand()) {
2092 LOperand* op = TryReuseSpillSlot(range); 2154 LOperand* op = TryReuseSpillSlot(range);
2093 if (op == NULL) op = chunk_->GetNextSpillSlot(mode_ == DOUBLE_REGISTERS); 2155 if (op == NULL) op = chunk_->GetNextSpillSlot(mode_ == DOUBLE_REGISTERS);
2094 first->SetSpillOperand(op); 2156 first->SetSpillOperand(op);
2157
2158 // This is the first time we are spilling a sibling of this range.
2159 // If the spill store was not eagerly at parent's start then we need
danno 2013/01/10 15:33:27 nit: not eagerly emitted
Vyacheslav Egorov (Google) 2013/01/25 13:49:17 Done.
2160 // to either emit it eagerly or postpone it for spill store sinking pass.
2161 if (first->HasPendingSpillStore()) {
2162 HBasicBlock* first_block = GetBlock(first->Start());
2163 HBasicBlock* loop_header = first_block->IsLoopHeader() ?
2164 first_block : first_block->parent_loop_header();
2165 if ((first != range) &&
2166 (loop_header != NULL) &&
2167 (GetBlock(range->Start())->parent_loop_header() != loop_header)) {
danno 2013/01/10 15:33:27 Why don't you have to handle the case there GetBlo
Vyacheslav Egorov (Google) 2013/01/25 13:49:17 Done.
2168 // If the range was defined inside the loop but is spilled outside then
2169 // we should try to sink corresponding spill store out of the loop to
2170 // reduce amount of memory writes.
danno 2013/01/10 15:33:27 You check that it's a different loop, but don't yo
Vyacheslav Egorov (Google) 2013/01/25 13:49:17 We are always moving spilling *up*, so it can't go
2171 pending_spilled_.Add(first, zone_);
2172 } else {
2173 EmitSpillStore(first);
2174 }
2175 }
2095 } 2176 }
2096 range->MakeSpilled(zone_); 2177 range->MakeSpilled(zone_);
2097 } 2178 }
2098 2179
2099 2180
2181 void LAllocator::EmitSpillStore(LiveRange* range) {
2182 ASSERT(range->HasPendingSpillStore());
2183 EmitSpillStore(range->spill_start_index(),
2184 range->spill_source(),
2185 range->GetSpillOperand());
2186 }
2187
2188
2189 void LAllocator::EmitSpillStore(int pos, LOperand* source, LOperand* spill) {
2190 // This move to spill operand is not a real use. Liveness analysis
2191 // and splitting of live ranges do not account for it.
2192 // Thus it should be inserted to a lifetime position corresponding to
2193 // the instruction end.
2194 LGap* gap = GapAt(pos);
2195 LParallelMove* move = gap->GetOrCreateParallelMove(LGap::BEFORE, zone());
2196 move->AddMove(source, spill, zone());
2197 }
2198
2199
2100 int LAllocator::RegisterCount() const { 2200 int LAllocator::RegisterCount() const {
2101 return num_registers_; 2201 return num_registers_;
2102 } 2202 }
2103 2203
2104 2204
2105 #ifdef DEBUG 2205 #ifdef DEBUG
2106 2206
2107 2207
2108 void LAllocator::Verify() const { 2208 void LAllocator::Verify() const {
2109 for (int i = 0; i < live_ranges()->length(); ++i) { 2209 for (int i = 0; i < live_ranges()->length(); ++i) {
2110 LiveRange* current = live_ranges()->at(i); 2210 LiveRange* current = live_ranges()->at(i);
2111 if (current != NULL) current->Verify(); 2211 if (current != NULL) current->Verify();
2112 } 2212 }
2113 } 2213 }
2114 2214
2115 2215
2116 #endif 2216 #endif
2117 2217
2118 2218
2119 } } // namespace v8::internal 2219 } } // namespace v8::internal
OLDNEW
« src/lithium-allocator.h ('K') | « src/lithium-allocator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698