Chromium Code Reviews| 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 2182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2193 } | 2193 } |
| 2194 | 2194 |
| 2195 | 2195 |
| 2196 void LiveRangeBuilder::ProcessPhis(const InstructionBlock* block, | 2196 void LiveRangeBuilder::ProcessPhis(const InstructionBlock* block, |
| 2197 BitVector* live) { | 2197 BitVector* live) { |
| 2198 for (PhiInstruction* phi : block->phis()) { | 2198 for (PhiInstruction* phi : block->phis()) { |
| 2199 // The live range interval already ends at the first instruction of the | 2199 // The live range interval already ends at the first instruction of the |
| 2200 // block. | 2200 // block. |
| 2201 int phi_vreg = phi->virtual_register(); | 2201 int phi_vreg = phi->virtual_register(); |
| 2202 live->Remove(phi_vreg); | 2202 live->Remove(phi_vreg); |
| 2203 // Select the hint from the first predecessor block that preceeds this block | 2203 // Select a hint from a predecessor block that preceeds this block in the |
| 2204 // in the rpo ordering. Prefer non-deferred blocks. The enforcement of | 2204 // rpo order. In order of priority: |
| 2205 // hinting in rpo order is required because hint resolution that happens | 2205 // - Avoid hints from deferred blocks. |
| 2206 // later in the compiler pipeline visits instructions in reverse rpo, | 2206 // - Prefer hints from allocated (or explicit) operands. |
| 2207 // relying on the fact that phis are encountered before their hints. | 2207 // - Prefer hints from empty blocks (containing just parallel moves and a |
| 2208 const Instruction* instr = nullptr; | 2208 // jump). This helps to avoid otherwise useless move + jump sequences. |
|
Mircea Trofin
2016/07/04 16:32:15
Nit: the moves wouldn't be useless, I think you're
jbramley
2016/07/04 16:58:54
Yes, that's what I meant. I'll re-word it.
| |
| 2209 const InstructionBlock::Predecessors& predecessors = block->predecessors(); | 2209 // The enforcement of hinting in rpo order is required because hint |
| 2210 for (size_t i = 0; i < predecessors.size(); ++i) { | 2210 // resolution that happens later in the compiler pipeline visits |
| 2211 // instructions in reverse rpo order, relying on the fact that phis are | |
| 2212 // encountered before their hints. | |
| 2213 InstructionOperand* hint = nullptr; | |
| 2214 int hint_preference = 0; | |
| 2215 | |
| 2216 for (RpoNumber predecessor : block->predecessors()) { | |
| 2211 const InstructionBlock* predecessor_block = | 2217 const InstructionBlock* predecessor_block = |
| 2212 code()->InstructionBlockAt(predecessors[i]); | 2218 code()->InstructionBlockAt(predecessor); |
| 2213 if (predecessor_block->rpo_number() < block->rpo_number()) { | 2219 DCHECK_EQ(predecessor_block->rpo_number(), predecessor); |
| 2214 instr = GetLastInstruction(code(), predecessor_block); | 2220 |
| 2215 if (!predecessor_block->IsDeferred()) break; | 2221 // Only take hints from earlier rpo numbers. |
| 2222 if (predecessor >= block->rpo_number()) continue; | |
| 2223 | |
| 2224 // Look up the predecessor instruction. | |
| 2225 const Instruction* predecessor_instr = | |
| 2226 GetLastInstruction(code(), predecessor_block); | |
| 2227 InstructionOperand* predecessor_hint = nullptr; | |
| 2228 // Phis are assigned in an END move after the last instruction in each | |
|
Mircea Trofin
2016/07/04 16:32:15
I think you meant to say "in the END position of t
jbramley
2016/07/04 16:58:54
Acknowledged.
| |
| 2229 // predecessor block. | |
| 2230 for (MoveOperands* move : | |
| 2231 *predecessor_instr->GetParallelMove(Instruction::END)) { | |
| 2232 InstructionOperand& to = move->destination(); | |
| 2233 if (to.IsUnallocated() && | |
| 2234 UnallocatedOperand::cast(to).virtual_register() == phi_vreg) { | |
| 2235 predecessor_hint = &move->source(); | |
| 2236 break; | |
| 2237 } | |
| 2238 } | |
| 2239 DCHECK_NOT_NULL(predecessor_hint); | |
| 2240 | |
| 2241 // For each predecessor, calculate a score according to the priorities | |
| 2242 // described above, and pick the best one. | |
| 2243 int predecessor_hint_preference = 0; | |
| 2244 const int kNotDeferredBlockPreference = 4; | |
| 2245 const int kMoveIsAllocatedPreference = 2; | |
| 2246 const int kBlockIsEmptyPreference = 1; | |
| 2247 | |
| 2248 // - Avoid hints from deferred blocks. | |
| 2249 if (!predecessor_block->IsDeferred()) { | |
| 2250 predecessor_hint_preference += kNotDeferredBlockPreference; | |
|
Mircea Trofin
2016/07/04 16:32:15
Nit: replace with bitwise or, I think that'd make
jbramley
2016/07/04 16:58:54
I'd half planned to support an arithmetic score, t
Mircea Trofin
2016/07/04 21:20:35
Oh - the fact that they are powers of 2 threw me o
| |
| 2251 } | |
| 2252 | |
| 2253 // - Prefer hints from allocated (or explicit) operands. | |
| 2254 // | |
| 2255 // Already-allocated or explicit operands are typically assigned using | |
| 2256 // the parallel moves on the last instruction. For example: | |
| 2257 // | |
| 2258 // gap (v101 = [x0|R|w32]) (v100 = v101) | |
| 2259 // ArchJmp | |
| 2260 // ... | |
| 2261 // phi: v100 = v101 v102 | |
| 2262 // | |
| 2263 // We have already found the END move, so look for a matching START move | |
| 2264 // from an allocated (or explicit) operand. | |
|
Mircea Trofin
2016/07/04 16:32:15
This happens if the previous instruction (the one
jbramley
2016/07/04 16:58:54
Reasonably common. Without this, the empty-block c
Mircea Trofin
2016/07/04 21:20:35
It may be worth investigating. The compile benchma
| |
| 2265 auto moves = predecessor_instr->GetParallelMove(Instruction::START); | |
| 2266 if (moves != nullptr) { | |
| 2267 for (MoveOperands* move : *moves) { | |
| 2268 InstructionOperand& to = move->destination(); | |
| 2269 if (predecessor_hint->Equals(to)) { | |
| 2270 if (move->source().IsAllocated() || move->source().IsExplicit()) { | |
| 2271 predecessor_hint_preference += kMoveIsAllocatedPreference; | |
| 2272 } | |
| 2273 break; | |
| 2274 } | |
| 2275 } | |
| 2276 } | |
| 2277 | |
| 2278 // - Prefer hints from empty blocks. | |
| 2279 if (predecessor_block->last_instruction_index() == | |
| 2280 predecessor_block->first_instruction_index()) { | |
| 2281 predecessor_hint_preference += kBlockIsEmptyPreference; | |
| 2282 } | |
| 2283 | |
| 2284 if ((hint == nullptr) || | |
| 2285 (predecessor_hint_preference > hint_preference)) { | |
| 2286 // Take the hint from this predecessor. | |
| 2287 hint = predecessor_hint; | |
| 2288 hint_preference = predecessor_hint_preference; | |
| 2216 } | 2289 } |
| 2217 } | 2290 } |
| 2218 DCHECK_NOT_NULL(instr); | 2291 DCHECK_NOT_NULL(hint); |
| 2219 | 2292 |
| 2220 InstructionOperand* hint = nullptr; | |
| 2221 for (MoveOperands* move : *instr->GetParallelMove(Instruction::END)) { | |
| 2222 InstructionOperand& to = move->destination(); | |
| 2223 if (to.IsUnallocated() && | |
| 2224 UnallocatedOperand::cast(to).virtual_register() == phi_vreg) { | |
| 2225 hint = &move->source(); | |
| 2226 break; | |
| 2227 } | |
| 2228 } | |
| 2229 DCHECK(hint != nullptr); | |
| 2230 LifetimePosition block_start = LifetimePosition::GapFromInstructionIndex( | 2293 LifetimePosition block_start = LifetimePosition::GapFromInstructionIndex( |
| 2231 block->first_instruction_index()); | 2294 block->first_instruction_index()); |
| 2232 UsePosition* use_pos = Define(block_start, &phi->output(), hint, | 2295 UsePosition* use_pos = Define(block_start, &phi->output(), hint, |
| 2233 UsePosition::HintTypeForOperand(*hint)); | 2296 UsePosition::HintTypeForOperand(*hint)); |
| 2234 MapPhiHint(hint, use_pos); | 2297 MapPhiHint(hint, use_pos); |
| 2235 } | 2298 } |
| 2236 } | 2299 } |
| 2237 | 2300 |
| 2238 | 2301 |
| 2239 void LiveRangeBuilder::ProcessLoopHeader(const InstructionBlock* block, | 2302 void LiveRangeBuilder::ProcessLoopHeader(const InstructionBlock* block, |
| (...skipping 1540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3780 } | 3843 } |
| 3781 } | 3844 } |
| 3782 } | 3845 } |
| 3783 } | 3846 } |
| 3784 } | 3847 } |
| 3785 | 3848 |
| 3786 | 3849 |
| 3787 } // namespace compiler | 3850 } // namespace compiler |
| 3788 } // namespace internal | 3851 } // namespace internal |
| 3789 } // namespace v8 | 3852 } // namespace v8 |
| OLD | NEW |