Revert "[Liftoff] Implement parallel register moves"

This reverts commit 6c6132880a.

Reason for revert: breaks compilation on win64 bot: https://build.chromium.org/p/client.v8/builders/V8%20Win64%20-%20msvc/builds/69

Original change's description:
> [Liftoff] Implement parallel register moves
> 
> This was not implemented so far, leading to lots of clusterfuzz issues.
> Testing this feature would require complicating the interface a lot and
> exposing more implementation details in the header file, hence we just
> go with regression tests for now.
> 
> R=​ahaas@chromium.org, titzer@chromium.org
> 
> Bug: v8:6600, chromium:782280
> Change-Id: I12863f3eb59a8dffdcc7d3bfb8e1f0ae0eec15ee
> Reviewed-on: https://chromium-review.googlesource.com/758772
> Reviewed-by: Andreas Haas <ahaas@chromium.org>
> Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#49286}

TBR=titzer@chromium.org,ahaas@chromium.org,clemensh@chromium.org

Change-Id: I386983da7f9f03d54cef2190b01fd2cc5785966e
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: v8:6600, chromium:782280
Reviewed-on: https://chromium-review.googlesource.com/763367
Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49289}
This commit is contained in:
Clemens Hammacher 2017-11-10 10:04:17 +00:00 committed by Commit Bot
parent 9eaf163d6f
commit 5a6cc315f8
2 changed files with 22 additions and 110 deletions

View File

@ -31,81 +31,15 @@ namespace {
} while (false)
class StackTransferRecipe {
struct RegisterMove {
Register dst;
Register src;
constexpr RegisterMove(Register dst, Register src) : dst(dst), src(src) {}
};
struct RegisterLoad {
Register dst;
bool is_constant_load; // otherwise load it from the stack.
union {
uint32_t stack_slot;
WasmValue constant;
};
RegisterLoad(Register dst, WasmValue constant)
: dst(dst), is_constant_load(true), constant(constant) {}
RegisterLoad(Register dst, uint32_t stack_slot)
: dst(dst), is_constant_load(false), stack_slot(stack_slot) {}
};
public:
explicit StackTransferRecipe(LiftoffAssembler* wasm_asm) : asm_(wasm_asm) {}
~StackTransferRecipe() { Execute(); }
void Execute() {
// First, execute register moves. Then load constants and stack values into
// registers.
if ((move_dst_regs & move_src_regs) == 0) {
// No overlap in src and dst registers. Just execute the moves in any
// order.
for (RegisterMove& rm : register_moves) asm_->Move(rm.dst, rm.src);
register_moves.clear();
} else {
// Keep use counters of src registers.
constexpr size_t kRegArrSize =
LiftoffAssembler::CacheState::kMaxRegisterCode + 1;
uint32_t src_reg_use_count[kRegArrSize] = {0};
for (RegisterMove& rm : register_moves) {
++src_reg_use_count[rm.src.code()];
}
// Now repeatedly iterate the list of register moves, and execute those
// whose dst register does not appear as src any more. The remaining moves
// are compacted during this iteration.
// If no more moves can be executed (because of a cycle), spill one
// register to the stack, add a RegisterLoad to reload it later, and
// continue.
uint32_t next_spill_slot = asm_->cache_state()->stack_height();
while (!register_moves.empty()) {
size_t executed_moves = 0;
for (auto& rm : register_moves) {
if (src_reg_use_count[rm.dst.code()] == 0) {
asm_->Move(rm.dst, rm.src);
++executed_moves;
DCHECK_LT(0, src_reg_use_count[rm.src.code()]);
--src_reg_use_count[rm.src.code()];
} else if (executed_moves) {
// Compaction: Move not-executed moves to the beginning of the list.
(&rm)[-executed_moves] = rm;
}
}
if (executed_moves == 0) {
// There is a cycle. Spill one register, then continue.
Register spill_reg = register_moves.back().src;
asm_->Spill(next_spill_slot, spill_reg);
// Remember to reload that register later.
LoadStackSlot(spill_reg, next_spill_slot);
DCHECK_EQ(1, src_reg_use_count[spill_reg.code()]);
src_reg_use_count[spill_reg.code()] = 0;
++next_spill_slot;
executed_moves = 1;
}
constexpr RegisterMove dummy(no_reg, no_reg);
register_moves.resize(register_moves.size() - executed_moves, dummy);
}
// TODO(clemensh): Find suitable schedule.
for (RegisterMove& rm : register_moves) {
asm_->Move(rm.dst, rm.src);
}
for (RegisterLoad& rl : register_loads) {
if (rl.is_constant_load) {
asm_->LoadConstant(rl.dst, rl.constant);
@ -113,7 +47,6 @@ class StackTransferRecipe {
asm_->Fill(rl.dst, rl.stack_slot);
}
}
register_loads.clear();
}
void TransferStackSlot(const LiftoffAssembler::CacheState& dst_state,
@ -157,9 +90,6 @@ class StackTransferRecipe {
}
void MoveRegister(Register dst, Register src) {
DCHECK_EQ(0, move_dst_regs & dst.bit());
move_dst_regs |= dst.bit();
move_src_regs |= src.bit();
register_moves.emplace_back(dst, src);
}
@ -172,12 +102,27 @@ class StackTransferRecipe {
}
private:
// TODO(clemensh): Avoid unconditionally allocating on the heap.
struct RegisterMove {
Register dst;
Register src;
RegisterMove(Register dst, Register src) : dst(dst), src(src) {}
};
struct RegisterLoad {
Register dst;
bool is_constant_load; // otherwise load it from the stack.
union {
uint32_t stack_slot;
WasmValue constant;
};
RegisterLoad(Register dst, WasmValue constant)
: dst(dst), is_constant_load(true), constant(constant) {}
RegisterLoad(Register dst, uint32_t stack_slot)
: dst(dst), is_constant_load(false), stack_slot(stack_slot) {}
};
std::vector<RegisterMove> register_moves;
std::vector<RegisterLoad> register_loads;
RegList move_dst_regs = 0;
RegList move_src_regs = 0;
LiftoffAssembler* const asm_;
LiftoffAssembler* asm_;
};
} // namespace

View File

@ -1,33 +0,0 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
load('test/mjsunit/wasm/wasm-constants.js');
load('test/mjsunit/wasm/wasm-module-builder.js');
var builder = new WasmModuleBuilder();
builder.addFunction('test', kSig_i_iii)
.addBodyWithEnd([
kExprI32Const, 0, // 0
kExprI32Const, 0, // 0, 0
kExprI32Add, // 0 + 0 -> 0
kExprI32Const, 0, // 0, 0
kExprI32Const, 0, // 0, 0, 0
kExprI32Add, // 0, 0 + 0 -> 0
kExprDrop, // 0
kExprDrop, // -
kExprI32Const, 0, // 0
kExprI32Const, 0, // 0, 0
kExprI32Add, // 0 + 0 -> 0
kExprI32Const, 0, // 0, 0
kExprI32Const, 1, // 0, 0, 1
kExprI32Add, // 0, 0 + 1 -> 1
kExprBlock, kWasmStmt, // 0, 1
kExprBr, 0, // 0, 1
kExprEnd, // 0, 1
kExprI32Add, // 0 + 1 -> 1
kExprEnd
])
.exportFunc();
var module = builder.instantiate();
assertEquals(1, module.exports.test());