[liftoff] Materialize constants before conditional branches
The number of constants stored in locals and the merge region can be arbitrarily big, thus generating arbitrarily long code for a single `br_if`. This happened in particular for unoptimized code. This CL solves this by materializing all constants (in registers or on the stack) before doing a conditional branch. This ensures that in a series of `br_if`s, each constant is only spilled once instead of on each single branch. For the linked bug, this reduces the total generated code size by ~36%. R=thibaudm@chromium.org Bug: chromium:1117033 Change-Id: I84ea2ea9ba4d3de9b042ceb223af15c3d73dc5b8 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2364498 Reviewed-by: Thibaud Michaud <thibaudm@chromium.org> Commit-Queue: Clemens Backes <clemensb@chromium.org> Cr-Commit-Position: refs/heads/master@{#69485}
This commit is contained in:
parent
1096e03159
commit
1a911e6cbe
@ -578,6 +578,28 @@ void LiftoffAssembler::PrepareLoopArgs(int num) {
|
||||
}
|
||||
}
|
||||
|
||||
void LiftoffAssembler::MaterializeMergedConstants(uint32_t arity) {
|
||||
// Materialize constants on top of the stack ({arity} many), and locals.
|
||||
VarState* stack_base = cache_state_.stack_state.data();
|
||||
for (auto slots :
|
||||
{VectorOf(stack_base + cache_state_.stack_state.size() - arity, arity),
|
||||
VectorOf(stack_base, num_locals())}) {
|
||||
for (VarState& slot : slots) {
|
||||
if (!slot.is_const()) continue;
|
||||
RegClass rc = reg_class_for(slot.type());
|
||||
if (cache_state_.has_unused_register(rc)) {
|
||||
LiftoffRegister reg = cache_state_.unused_register(rc);
|
||||
LoadConstant(reg, slot.constant());
|
||||
cache_state_.inc_used(reg);
|
||||
slot.MakeRegister(reg);
|
||||
} else {
|
||||
Spill(slot.offset(), slot.constant());
|
||||
slot.MakeStack();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LiftoffAssembler::MergeFullStackWith(const CacheState& target,
|
||||
const CacheState& source) {
|
||||
DCHECK_EQ(source.stack_height(), target.stack_height());
|
||||
|
@ -381,6 +381,8 @@ class LiftoffAssembler : public TurboAssembler {
|
||||
return SpillOneRegister(candidates, pinned);
|
||||
}
|
||||
|
||||
void MaterializeMergedConstants(uint32_t arity);
|
||||
|
||||
void MergeFullStackWith(const CacheState& target, const CacheState& source);
|
||||
void MergeStackWith(const CacheState& target, uint32_t arity);
|
||||
|
||||
|
@ -1840,6 +1840,14 @@ class LiftoffCompiler {
|
||||
}
|
||||
|
||||
void BrIf(FullDecoder* decoder, const Value& /* cond */, uint32_t depth) {
|
||||
// Before branching, materialize all constants. This avoids repeatedly
|
||||
// materializing them for each conditional branch.
|
||||
// TODO(clemensb): Do the same for br_table.
|
||||
if (depth != decoder->control_depth() - 1) {
|
||||
__ MaterializeMergedConstants(
|
||||
decoder->control_at(depth)->br_merge()->arity);
|
||||
}
|
||||
|
||||
Label cont_false;
|
||||
Register value = __ PopToRegister().gp();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user