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

Side by Side Diff: src/compiler/register-allocator.cc

Issue 2125463002: Improve phi hinting heuristics. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 5 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
« no previous file with comments | « no previous file | 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 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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698