Commit 184213d3 authored by Clemens Backes's avatar Clemens Backes Committed by V8 LUCI CQ

[compiler] Fall back to mid-tier register allocation

Huge functions can take a really long time (several minutes) in register
allocation. This is caused by a big number of virtual registers combined
with a big number of blocks.
We can avoid such long-running register allocation by falling back to
the mid-tier register allocation if we detect a huge number of virtual
registers.
Note that this is mostly relevant for bigger WebAssembly modules, but we
implement it as a general TurboFan flag.

The flag is off by default for now, since there seem to be bugs lurking
in the mid-tier register allocator. Once those are fixed, we can stage
it behind --future and then ship it.

R=mslekova@chromium.org
CC=thibaudm@chromium.org

Bug: v8:12320
Change-Id: Iff14de456c2b3a91ee2b2b12221295dd56b69463
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3231336Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77461}
parent 70a0baaa
......@@ -3553,20 +3553,33 @@ bool PipelineImpl::SelectInstructions(Linkage* linkage) {
bool run_verifier = FLAG_turbo_verify_allocation;
// Allocate registers.
// This limit is chosen somewhat arbitrarily, by looking at a few bigger
// WebAssembly programs, and chosing the limit such that functions that take
// >100ms in register allocation are switched to mid-tier.
static int kTopTierVirtualRegistersLimit = 8192;
const RegisterConfiguration* config = RegisterConfiguration::Default();
std::unique_ptr<const RegisterConfiguration> restricted_config;
bool use_mid_tier_register_allocator =
(data->info()->IsTurboprop() && FLAG_turboprop_mid_tier_reg_alloc) ||
(FLAG_turbo_use_mid_tier_regalloc_for_huge_functions &&
data->sequence()->VirtualRegisterCount() >
kTopTierVirtualRegistersLimit);
if (call_descriptor->HasRestrictedAllocatableRegisters()) {
RegList registers = call_descriptor->AllocatableRegisters();
DCHECK_LT(0, NumRegs(registers));
std::unique_ptr<const RegisterConfiguration> config;
config.reset(RegisterConfiguration::RestrictGeneralRegisters(registers));
AllocateRegistersForTopTier(config.get(), call_descriptor, run_verifier);
} else {
const RegisterConfiguration* config = RegisterConfiguration::Default();
if (data->info()->IsTurboprop() && FLAG_turboprop_mid_tier_reg_alloc) {
restricted_config.reset(
RegisterConfiguration::RestrictGeneralRegisters(registers));
config = restricted_config.get();
use_mid_tier_register_allocator = false;
}
if (use_mid_tier_register_allocator) {
AllocateRegistersForMidTier(config, call_descriptor, run_verifier);
} else {
AllocateRegistersForTopTier(config, call_descriptor, run_verifier);
}
}
// Verify the instruction sequence has the same hash in two stages.
VerifyGeneratedCodeIsIdempotent();
......
......@@ -916,6 +916,9 @@ DEFINE_BOOL(turbo_dynamic_map_checks, false,
DEFINE_BOOL(turbo_compress_translation_arrays, false,
"compress translation arrays (experimental)")
DEFINE_BOOL(turbo_inline_js_wasm_calls, true, "inline JS->Wasm calls")
DEFINE_BOOL(turbo_use_mid_tier_regalloc_for_huge_functions, false,
"fall back to the mid-tier register allocator for huge functions "
"(experimental)")
DEFINE_BOOL(turbo_optimize_apply, true, "optimize Function.prototype.apply")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment