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

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

Issue 309373002: ARM64: Regenerate instead of spilling and restoring cheap lithium instructions. Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 6 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/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 // 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 "v8.h" 5 #include "v8.h"
6 #include "lithium-allocator-inl.h" 6 #include "lithium-allocator-inl.h"
7 7
8 #include "hydrogen.h" 8 #include "hydrogen.h"
9 #include "string-stream.h" 9 #include "string-stream.h"
10 10
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 assigned_register_(kInvalidAssignment), 117 assigned_register_(kInvalidAssignment),
118 last_interval_(NULL), 118 last_interval_(NULL),
119 first_interval_(NULL), 119 first_interval_(NULL),
120 first_pos_(NULL), 120 first_pos_(NULL),
121 parent_(NULL), 121 parent_(NULL),
122 next_(NULL), 122 next_(NULL),
123 current_interval_(NULL), 123 current_interval_(NULL),
124 last_processed_use_(NULL), 124 last_processed_use_(NULL),
125 current_hint_operand_(NULL), 125 current_hint_operand_(NULL),
126 spill_operand_(new(zone) LOperand()), 126 spill_operand_(new(zone) LOperand()),
127 spill_start_index_(kMaxInt) { } 127 spill_start_index_(kMaxInt),
128 parent_linstr_(NULL) { }
128 129
129 130
130 void LiveRange::set_assigned_register(int reg, Zone* zone) { 131 void LiveRange::set_assigned_register(int reg, Zone* zone) {
131 ASSERT(!HasRegisterAssigned() && !IsSpilled()); 132 ASSERT(!HasRegisterAssigned() && !IsSpilled());
132 assigned_register_ = reg; 133 assigned_register_ = reg;
133 ConvertOperands(zone); 134 ConvertOperands(zone);
134 } 135 }
135 136
136 137
137 void LiveRange::MakeSpilled(Zone* zone) { 138 void LiveRange::MakeSpilled(Zone* zone) {
138 ASSERT(!IsSpilled()); 139 ASSERT(!IsSpilled());
139 ASSERT(TopLevel()->HasAllocatedSpillOperand()); 140 ASSERT(TopLevel()->HasAllocatedSpillOperand());
140 spilled_ = true; 141 spilled_ = true;
141 assigned_register_ = kInvalidAssignment; 142 assigned_register_ = kInvalidAssignment;
142 ConvertOperands(zone); 143 ConvertOperands(zone);
144 spill_operand_->set_parent_linstr(parent_linstr());
143 } 145 }
144 146
145 147
146 bool LiveRange::HasAllocatedSpillOperand() const { 148 bool LiveRange::HasAllocatedSpillOperand() const {
147 ASSERT(spill_operand_ != NULL); 149 ASSERT(spill_operand_ != NULL);
148 return !spill_operand_->IsIgnored(); 150 return !spill_operand_->IsIgnored();
149 } 151 }
150 152
151 153
152 void LiveRange::SetSpillOperand(LOperand* operand) { 154 void LiveRange::SetSpillOperand(LOperand* operand) {
153 ASSERT(!operand->IsUnallocated()); 155 ASSERT(!operand->IsUnallocated());
154 ASSERT(spill_operand_ != NULL); 156 ASSERT(spill_operand_ != NULL);
155 ASSERT(spill_operand_->IsIgnored()); 157 ASSERT(spill_operand_->IsIgnored());
158 ASSERT((spill_operand_->parent_linstr() == NULL) ||
159 (spill_operand_->parent_linstr() == parent_linstr()));
156 spill_operand_->ConvertTo(operand->kind(), operand->index()); 160 spill_operand_->ConvertTo(operand->kind(), operand->index());
161 spill_operand_->set_parent_linstr(parent_linstr());
157 } 162 }
158 163
159 164
160 UsePosition* LiveRange::NextUsePosition(LifetimePosition start) { 165 UsePosition* LiveRange::NextUsePosition(LifetimePosition start) {
161 UsePosition* use_pos = last_processed_use_; 166 UsePosition* use_pos = last_processed_use_;
162 if (use_pos == NULL) use_pos = first_pos(); 167 if (use_pos == NULL) use_pos = first_pos();
163 while (use_pos != NULL && use_pos->pos().Value() < start.Value()) { 168 while (use_pos != NULL && use_pos->pos().Value() < start.Value()) {
164 use_pos = use_pos->next(); 169 use_pos = use_pos->next();
165 } 170 }
166 last_processed_use_ = use_pos; 171 last_processed_use_ = use_pos;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 // at the current or the immediate next position. 209 // at the current or the immediate next position.
205 UsePosition* use_pos = NextRegisterPosition(pos); 210 UsePosition* use_pos = NextRegisterPosition(pos);
206 if (use_pos == NULL) return true; 211 if (use_pos == NULL) return true;
207 return 212 return
208 use_pos->pos().Value() > pos.NextInstruction().InstructionEnd().Value(); 213 use_pos->pos().Value() > pos.NextInstruction().InstructionEnd().Value();
209 } 214 }
210 215
211 216
212 LOperand* LiveRange::CreateAssignedOperand(Zone* zone) { 217 LOperand* LiveRange::CreateAssignedOperand(Zone* zone) {
213 LOperand* op = NULL; 218 LOperand* op = NULL;
219 bool allow_use_cache = parent_linstr() == NULL;
214 if (HasRegisterAssigned()) { 220 if (HasRegisterAssigned()) {
215 ASSERT(!IsSpilled()); 221 ASSERT(!IsSpilled());
216 switch (Kind()) { 222 switch (Kind()) {
217 case GENERAL_REGISTERS: 223 case GENERAL_REGISTERS:
218 op = LRegister::Create(assigned_register(), zone); 224 op = LRegister::Create(assigned_register(), zone, allow_use_cache);
219 break; 225 break;
220 case DOUBLE_REGISTERS: 226 case DOUBLE_REGISTERS:
221 op = LDoubleRegister::Create(assigned_register(), zone); 227 op = LDoubleRegister::Create(assigned_register(), zone,
228 allow_use_cache);
222 break; 229 break;
223 default: 230 default:
224 UNREACHABLE(); 231 UNREACHABLE();
225 } 232 }
226 } else if (IsSpilled()) { 233 } else if (IsSpilled()) {
227 ASSERT(!HasRegisterAssigned()); 234 ASSERT(!HasRegisterAssigned());
228 op = TopLevel()->GetSpillOperand(); 235 op = TopLevel()->GetSpillOperand();
229 ASSERT(!op->IsUnallocated()); 236 ASSERT(!op->IsUnallocated());
237 ASSERT(op->parent_linstr() == parent_linstr());
230 } else { 238 } else {
231 LUnallocated* unalloc = new(zone) LUnallocated(LUnallocated::NONE); 239 LUnallocated* unalloc = new(zone) LUnallocated(LUnallocated::NONE);
232 unalloc->set_virtual_register(id_); 240 unalloc->set_virtual_register(id_);
233 op = unalloc; 241 op = unalloc;
234 } 242 }
243 op->set_parent_linstr(parent_linstr());
235 return op; 244 return op;
236 } 245 }
237 246
238 247
239 UseInterval* LiveRange::FirstSearchIntervalForPosition( 248 UseInterval* LiveRange::FirstSearchIntervalForPosition(
240 LifetimePosition position) const { 249 LifetimePosition position) const {
241 if (current_interval_ == NULL) return first_interval_; 250 if (current_interval_ == NULL) return first_interval_;
242 if (current_interval_->start().Value() > position.Value()) { 251 if (current_interval_->start().Value() > position.Value()) {
243 current_interval_ = NULL; 252 current_interval_ = NULL;
244 return first_interval_; 253 return first_interval_;
(...skipping 13 matching lines...) Expand all
258 current_interval_ = to_start_of; 267 current_interval_ = to_start_of;
259 } 268 }
260 } 269 }
261 270
262 271
263 void LiveRange::SplitAt(LifetimePosition position, 272 void LiveRange::SplitAt(LifetimePosition position,
264 LiveRange* result, 273 LiveRange* result,
265 Zone* zone) { 274 Zone* zone) {
266 ASSERT(Start().Value() < position.Value()); 275 ASSERT(Start().Value() < position.Value());
267 ASSERT(result->IsEmpty()); 276 ASSERT(result->IsEmpty());
277
278 result->set_parent_linstr(parent_linstr());
279
268 // Find the last interval that ends before the position. If the 280 // Find the last interval that ends before the position. If the
269 // position is contained in one of the intervals in the chain, we 281 // position is contained in one of the intervals in the chain, we
270 // split that interval and use the first part. 282 // split that interval and use the first part.
271 UseInterval* current = FirstSearchIntervalForPosition(position); 283 UseInterval* current = FirstSearchIntervalForPosition(position);
272 284
273 // If the split position coincides with the beginning of a use interval 285 // If the split position coincides with the beginning of a use interval
274 // we need to split use positons in a special way. 286 // we need to split use positons in a special way.
275 bool split_at_start = false; 287 bool split_at_start = false;
276 288
277 if (current->start().Value() == position.Value()) { 289 if (current->start().Value() == position.Value()) {
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after
686 int index = LUnallocated::cast(operand)->virtual_register(); 698 int index = LUnallocated::cast(operand)->virtual_register();
687 HValue* instr = graph_->LookupValue(index); 699 HValue* instr = graph_->LookupValue(index);
688 if (instr != NULL && instr->IsPhi()) { 700 if (instr != NULL && instr->IsPhi()) {
689 return HPhi::cast(instr); 701 return HPhi::cast(instr);
690 } 702 }
691 return NULL; 703 return NULL;
692 } 704 }
693 705
694 706
695 LiveRange* LAllocator::LiveRangeFor(LOperand* operand) { 707 LiveRange* LAllocator::LiveRangeFor(LOperand* operand) {
708 LiveRange* result;
696 if (operand->IsUnallocated()) { 709 if (operand->IsUnallocated()) {
697 return LiveRangeFor(LUnallocated::cast(operand)->virtual_register()); 710 result = LiveRangeFor(LUnallocated::cast(operand)->virtual_register());
698 } else if (operand->IsRegister()) { 711 } else if (operand->IsRegister()) {
699 return FixedLiveRangeFor(operand->index()); 712 result = FixedLiveRangeFor(operand->index());
700 } else if (operand->IsDoubleRegister()) { 713 } else if (operand->IsDoubleRegister()) {
701 return FixedDoubleLiveRangeFor(operand->index()); 714 result = FixedDoubleLiveRangeFor(operand->index());
702 } else { 715 } else {
703 return NULL; 716 return NULL;
704 } 717 }
718 result->set_parent_linstr(operand->parent_linstr());
719 return result;
705 } 720 }
706 721
707 722
708 void LAllocator::Define(LifetimePosition position, 723 void LAllocator::Define(LifetimePosition position,
709 LOperand* operand, 724 LOperand* operand,
710 LOperand* hint) { 725 LOperand* hint) {
711 LiveRange* range = LiveRangeFor(operand); 726 LiveRange* range = LiveRangeFor(operand);
712 if (range == NULL) return; 727 if (range == NULL) return;
713 728
714 if (range->IsEmpty() || range->Start().Value() > position.Value()) { 729 if (range->IsEmpty() || range->Start().Value() > position.Value()) {
(...skipping 998 matching lines...) Expand 10 before | Expand all | Expand 10 after
1713 return true; 1728 return true;
1714 } 1729 }
1715 1730
1716 1731
1717 void LAllocator::FreeSpillSlot(LiveRange* range) { 1732 void LAllocator::FreeSpillSlot(LiveRange* range) {
1718 // Check that we are the last range. 1733 // Check that we are the last range.
1719 if (range->next() != NULL) return; 1734 if (range->next() != NULL) return;
1720 1735
1721 if (!range->TopLevel()->HasAllocatedSpillOperand()) return; 1736 if (!range->TopLevel()->HasAllocatedSpillOperand()) return;
1722 1737
1738 if (range->parent_linstr() != NULL) {
1739 // Reusing live ranges with parent instruction information may prevent
1740 // optimizing away gap moves.
1741 return;
1742 }
1743
1723 int index = range->TopLevel()->GetSpillOperand()->index(); 1744 int index = range->TopLevel()->GetSpillOperand()->index();
1724 if (index >= 0) { 1745 if (index >= 0) {
1725 reusable_slots_.Add(range, zone()); 1746 reusable_slots_.Add(range, zone());
1726 } 1747 }
1727 } 1748 }
1728 1749
1729 1750
1730 LOperand* LAllocator::TryReuseSpillSlot(LiveRange* range) { 1751 LOperand* LAllocator::TryReuseSpillSlot(LiveRange* range) {
1731 if (reusable_slots_.is_empty()) return NULL; 1752 if (reusable_slots_.is_empty()) return NULL;
1732 if (reusable_slots_.first()->End().Value() > 1753 if (reusable_slots_.first()->End().Value() >
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after
2142 // Nothing to spill. Just put it to unhandled as whole. 2163 // Nothing to spill. Just put it to unhandled as whole.
2143 AddToUnhandledSorted(second_part); 2164 AddToUnhandledSorted(second_part);
2144 } 2165 }
2145 } 2166 }
2146 2167
2147 2168
2148 void LAllocator::Spill(LiveRange* range) { 2169 void LAllocator::Spill(LiveRange* range) {
2149 ASSERT(!range->IsSpilled()); 2170 ASSERT(!range->IsSpilled());
2150 TraceAlloc("Spilling live range %d\n", range->id()); 2171 TraceAlloc("Spilling live range %d\n", range->id());
2151 LiveRange* first = range->TopLevel(); 2172 LiveRange* first = range->TopLevel();
2173 ASSERT(first->parent_linstr() == range->parent_linstr());
2152 2174
2153 if (!first->HasAllocatedSpillOperand()) { 2175 if (!first->HasAllocatedSpillOperand()) {
2154 LOperand* op = TryReuseSpillSlot(range); 2176 LOperand* op = TryReuseSpillSlot(range);
2155 if (op == NULL) op = chunk_->GetNextSpillSlot(range->Kind()); 2177 if (op == NULL) op = chunk_->GetNextSpillSlot(range->Kind());
2156 first->SetSpillOperand(op); 2178 first->SetSpillOperand(op);
2157 } 2179 }
2158 range->MakeSpilled(chunk()->zone()); 2180 range->MakeSpilled(chunk()->zone());
2159 } 2181 }
2160 2182
2161 2183
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2200 isolate()->GetHTracer()->TraceLiveRanges(name(), allocator_); 2222 isolate()->GetHTracer()->TraceLiveRanges(name(), allocator_);
2201 } 2223 }
2202 2224
2203 #ifdef DEBUG 2225 #ifdef DEBUG
2204 if (allocator_ != NULL) allocator_->Verify(); 2226 if (allocator_ != NULL) allocator_->Verify();
2205 #endif 2227 #endif
2206 } 2228 }
2207 2229
2208 2230
2209 } } // namespace v8::internal 2231 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/lithium-allocator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698