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/base/adapters.h" | 5 #include "src/base/adapters.h" |
6 #include "src/compiler/linkage.h" | 6 #include "src/compiler/linkage.h" |
7 #include "src/compiler/register-allocator.h" | 7 #include "src/compiler/register-allocator.h" |
8 #include "src/string-stream.h" | 8 #include "src/string-stream.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
(...skipping 3156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3167 } | 3167 } |
3168 } | 3168 } |
3169 } | 3169 } |
3170 } | 3170 } |
3171 | 3171 |
3172 | 3172 |
3173 namespace { | 3173 namespace { |
3174 | 3174 |
3175 class LiveRangeBound { | 3175 class LiveRangeBound { |
3176 public: | 3176 public: |
3177 explicit LiveRangeBound(const LiveRange* range) | 3177 explicit LiveRangeBound(const LiveRange* range, bool skip) |
3178 : range_(range), start_(range->Start()), end_(range->End()) { | 3178 : range_(range), start_(range->Start()), end_(range->End()), skip_(skip) { |
3179 DCHECK(!range->IsEmpty()); | 3179 DCHECK(!range->IsEmpty()); |
3180 } | 3180 } |
3181 | 3181 |
3182 bool CanCover(LifetimePosition position) { | 3182 bool CanCover(LifetimePosition position) { |
3183 return start_ <= position && position < end_; | 3183 return start_ <= position && position < end_; |
3184 } | 3184 } |
3185 | 3185 |
3186 const LiveRange* const range_; | 3186 const LiveRange* const range_; |
3187 const LifetimePosition start_; | 3187 const LifetimePosition start_; |
3188 const LifetimePosition end_; | 3188 const LifetimePosition end_; |
| 3189 const bool skip_; |
3189 | 3190 |
3190 private: | 3191 private: |
3191 DISALLOW_COPY_AND_ASSIGN(LiveRangeBound); | 3192 DISALLOW_COPY_AND_ASSIGN(LiveRangeBound); |
3192 }; | 3193 }; |
3193 | 3194 |
3194 | 3195 |
3195 struct FindResult { | 3196 struct FindResult { |
3196 const LiveRange* cur_cover_; | 3197 const LiveRange* cur_cover_; |
3197 const LiveRange* pred_cover_; | 3198 const LiveRange* pred_cover_; |
3198 }; | 3199 }; |
3199 | 3200 |
3200 | 3201 |
3201 class LiveRangeBoundArray { | 3202 class LiveRangeBoundArray { |
3202 public: | 3203 public: |
3203 LiveRangeBoundArray() : length_(0), start_(nullptr) {} | 3204 LiveRangeBoundArray() : length_(0), start_(nullptr) {} |
3204 | 3205 |
3205 bool ShouldInitialize() { return start_ == nullptr; } | 3206 bool ShouldInitialize() { return start_ == nullptr; } |
3206 | 3207 |
3207 void Initialize(Zone* zone, const LiveRange* const range) { | 3208 void Initialize(Zone* zone, const TopLevelLiveRange* const range) { |
3208 size_t length = 0; | 3209 length_ = range->GetChildCount(); |
3209 for (auto i = range; i != nullptr; i = i->next()) length++; | 3210 |
3210 start_ = zone->NewArray<LiveRangeBound>(length); | 3211 start_ = zone->NewArray<LiveRangeBound>(length_); |
3211 length_ = length; | 3212 LiveRangeBound* curr = start_; |
3212 auto curr = start_; | 3213 // Normally, spilled ranges do not need connecting moves, because the spill |
3213 for (auto i = range; i != nullptr; i = i->next(), ++curr) { | 3214 // location has been assigned at definition. For ranges spilled in deferred |
3214 new (curr) LiveRangeBound(i); | 3215 // blocks, that is not the case, so we need to connect the spilled children. |
| 3216 bool spilled_in_blocks = range->IsSpilledOnlyInDeferredBlocks(); |
| 3217 for (const LiveRange *i = range; i != nullptr; i = i->next(), ++curr) { |
| 3218 new (curr) LiveRangeBound(i, !spilled_in_blocks && i->spilled()); |
3215 } | 3219 } |
3216 } | 3220 } |
3217 | 3221 |
3218 LiveRangeBound* Find(const LifetimePosition position) const { | 3222 LiveRangeBound* Find(const LifetimePosition position) const { |
3219 size_t left_index = 0; | 3223 size_t left_index = 0; |
3220 size_t right_index = length_; | 3224 size_t right_index = length_; |
3221 while (true) { | 3225 while (true) { |
3222 size_t current_index = left_index + (right_index - left_index) / 2; | 3226 size_t current_index = left_index + (right_index - left_index) / 2; |
3223 DCHECK(right_index > current_index); | 3227 DCHECK(right_index > current_index); |
3224 auto bound = &start_[current_index]; | 3228 auto bound = &start_[current_index]; |
(...skipping 12 matching lines...) Expand all Loading... |
3237 pred->last_instruction_index()); | 3241 pred->last_instruction_index()); |
3238 return Find(pred_end); | 3242 return Find(pred_end); |
3239 } | 3243 } |
3240 | 3244 |
3241 LiveRangeBound* FindSucc(const InstructionBlock* succ) { | 3245 LiveRangeBound* FindSucc(const InstructionBlock* succ) { |
3242 auto succ_start = LifetimePosition::GapFromInstructionIndex( | 3246 auto succ_start = LifetimePosition::GapFromInstructionIndex( |
3243 succ->first_instruction_index()); | 3247 succ->first_instruction_index()); |
3244 return Find(succ_start); | 3248 return Find(succ_start); |
3245 } | 3249 } |
3246 | 3250 |
3247 void Find(const InstructionBlock* block, const InstructionBlock* pred, | 3251 bool FindConnectableSubranges(const InstructionBlock* block, |
3248 FindResult* result) const { | 3252 const InstructionBlock* pred, |
3249 auto pred_end = LifetimePosition::InstructionFromInstructionIndex( | 3253 FindResult* result) const { |
3250 pred->last_instruction_index()); | 3254 LifetimePosition pred_end = |
3251 auto bound = Find(pred_end); | 3255 LifetimePosition::InstructionFromInstructionIndex( |
| 3256 pred->last_instruction_index()); |
| 3257 LiveRangeBound* bound = Find(pred_end); |
3252 result->pred_cover_ = bound->range_; | 3258 result->pred_cover_ = bound->range_; |
3253 auto cur_start = LifetimePosition::GapFromInstructionIndex( | 3259 LifetimePosition cur_start = LifetimePosition::GapFromInstructionIndex( |
3254 block->first_instruction_index()); | 3260 block->first_instruction_index()); |
3255 // Common case. | 3261 |
3256 if (bound->CanCover(cur_start)) { | 3262 if (bound->CanCover(cur_start)) { |
3257 result->cur_cover_ = bound->range_; | 3263 // Both blocks are covered by the same range, so there is nothing to |
3258 return; | 3264 // connect. |
| 3265 return false; |
3259 } | 3266 } |
3260 result->cur_cover_ = Find(cur_start)->range_; | 3267 bound = Find(cur_start); |
| 3268 if (bound->skip_) { |
| 3269 return false; |
| 3270 } |
| 3271 result->cur_cover_ = bound->range_; |
3261 DCHECK(result->pred_cover_ != nullptr && result->cur_cover_ != nullptr); | 3272 DCHECK(result->pred_cover_ != nullptr && result->cur_cover_ != nullptr); |
| 3273 return (result->cur_cover_ != result->pred_cover_); |
3262 } | 3274 } |
3263 | 3275 |
3264 private: | 3276 private: |
3265 size_t length_; | 3277 size_t length_; |
3266 LiveRangeBound* start_; | 3278 LiveRangeBound* start_; |
3267 | 3279 |
3268 DISALLOW_COPY_AND_ASSIGN(LiveRangeBoundArray); | 3280 DISALLOW_COPY_AND_ASSIGN(LiveRangeBoundArray); |
3269 }; | 3281 }; |
3270 | 3282 |
3271 | 3283 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3339 auto& live_in_sets = data()->live_in_sets(); | 3351 auto& live_in_sets = data()->live_in_sets(); |
3340 for (auto block : code()->instruction_blocks()) { | 3352 for (auto block : code()->instruction_blocks()) { |
3341 if (CanEagerlyResolveControlFlow(block)) continue; | 3353 if (CanEagerlyResolveControlFlow(block)) continue; |
3342 auto live = live_in_sets[block->rpo_number().ToInt()]; | 3354 auto live = live_in_sets[block->rpo_number().ToInt()]; |
3343 BitVector::Iterator iterator(live); | 3355 BitVector::Iterator iterator(live); |
3344 while (!iterator.Done()) { | 3356 while (!iterator.Done()) { |
3345 auto* array = finder.ArrayFor(iterator.Current()); | 3357 auto* array = finder.ArrayFor(iterator.Current()); |
3346 for (auto pred : block->predecessors()) { | 3358 for (auto pred : block->predecessors()) { |
3347 FindResult result; | 3359 FindResult result; |
3348 const auto* pred_block = code()->InstructionBlockAt(pred); | 3360 const auto* pred_block = code()->InstructionBlockAt(pred); |
3349 array->Find(block, pred_block, &result); | 3361 if (!array->FindConnectableSubranges(block, pred_block, &result)) { |
3350 if (result.cur_cover_ == result.pred_cover_ || | |
3351 (!result.cur_cover_->TopLevel()->IsSpilledOnlyInDeferredBlocks() && | |
3352 result.cur_cover_->spilled())) | |
3353 continue; | 3362 continue; |
| 3363 } |
3354 auto pred_op = result.pred_cover_->GetAssignedOperand(); | 3364 auto pred_op = result.pred_cover_->GetAssignedOperand(); |
3355 auto cur_op = result.cur_cover_->GetAssignedOperand(); | 3365 auto cur_op = result.cur_cover_->GetAssignedOperand(); |
3356 if (pred_op.Equals(cur_op)) continue; | 3366 if (pred_op.Equals(cur_op)) continue; |
3357 ResolveControlFlow(block, cur_op, pred_block, pred_op); | 3367 ResolveControlFlow(block, cur_op, pred_block, pred_op); |
3358 } | 3368 } |
3359 iterator.Advance(); | 3369 iterator.Advance(); |
3360 } | 3370 } |
3361 } | 3371 } |
3362 } | 3372 } |
3363 | 3373 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3455 auto eliminate = moves->PrepareInsertAfter(move); | 3465 auto eliminate = moves->PrepareInsertAfter(move); |
3456 to_insert.push_back(move); | 3466 to_insert.push_back(move); |
3457 if (eliminate != nullptr) to_eliminate.push_back(eliminate); | 3467 if (eliminate != nullptr) to_eliminate.push_back(eliminate); |
3458 } | 3468 } |
3459 } | 3469 } |
3460 | 3470 |
3461 | 3471 |
3462 } // namespace compiler | 3472 } // namespace compiler |
3463 } // namespace internal | 3473 } // namespace internal |
3464 } // namespace v8 | 3474 } // namespace v8 |
OLD | NEW |