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:
parent
9eaf163d6f
commit
5a6cc315f8
@ -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
|
||||
|
@ -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());
|
Loading…
Reference in New Issue
Block a user