[vm] Introduce --target-unknown-cpu option and use it for app-jit snapshots

App-jit and core-jit snapshots generated on one machine can be copied to
another machine with different CPU family/model, so it is incorrect to
use CPU features of the host machine to generate code for snapshots.

This change adds --target-unknown-cpu option and enables it when
generating app-jit and core-jit snapshots in standalone Dart VM and
gen_snapshot.

Currently, this flag disables SSE4.1, popcnt and ABM on ia32 and x64,
and integer division instruction on ARM. Also, new flag enables
testing of roundsd instruction availability at run time on x64
(similarly to AOT).

TEST=ci
Fixes https://github.com/dart-lang/sdk/issues/47907
Fixes https://github.com/flutter/flutter/issues/94181

Change-Id: Id28448052a21df4bae30b39e62b8532e55d4c901
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/223960
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
Alexander Markov 2021-12-16 21:33:49 +00:00 committed by Commit Bot
parent 8784f9682d
commit b80e682cbf
10 changed files with 35 additions and 22 deletions

View file

@ -879,6 +879,10 @@ int main(int argc, char** argv) {
if (IsSnapshottingForPrecompilation()) {
vm_options.AddArgument("--precompilation");
} else if ((snapshot_kind == kCoreJIT) || (snapshot_kind == kAppJIT)) {
// Core-jit and app-jit snapshot can be deployed to another machine,
// so generated code should not depend on the CPU features
// of the system where snapshot was generated.
vm_options.AddArgument("--target-unknown-cpu");
#if !defined(TARGET_ARCH_IA32)
vm_options.AddArgument("--link_natives_lazily");
#endif

View file

@ -1242,6 +1242,12 @@ void main(int argc, char** argv) {
#if defined(DART_PRECOMPILED_RUNTIME)
vm_options.AddArgument("--precompilation");
#endif
if (Options::gen_snapshot_kind() == kAppJIT) {
// App-jit snapshot can be deployed to another machine,
// so generated code should not depend on the CPU features
// of the system where snapshot was generated.
vm_options.AddArgument("--target-unknown-cpu");
}
// If we need to write an app-jit snapshot or a depfile, then add an exit
// hook that writes the snapshot and/or depfile as appropriate.
if ((Options::gen_snapshot_kind() == kAppJIT) ||

View file

@ -223,16 +223,14 @@ void FlowGraphCompiler::InitCompiler() {
BlockEntryInstr* entry = block_order_[i];
for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
Instruction* current = it.Current();
if (current->IsBranch()) {
current = current->AsBranch()->comparison();
if (auto* branch = current->AsBranch()) {
current = branch->comparison();
}
// In optimized code, ICData is always set in the instructions.
const ICData* ic_data = NULL;
if (current->IsInstanceCall()) {
ic_data = current->AsInstanceCall()->ic_data();
}
if ((ic_data != NULL) && (ic_data->NumberOfUsedChecks() == 0)) {
may_reoptimize_ = true;
if (auto* instance_call = current->AsInstanceCall()) {
const ICData* ic_data = instance_call->ic_data();
if ((ic_data == nullptr) || (ic_data->NumberOfUsedChecks() == 0)) {
may_reoptimize_ = true;
}
}
}
}

View file

@ -5241,11 +5241,12 @@ void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
compiler->AddSlowPathCode(slow_path);
if (recognized_kind() != MethodRecognizer::kDoubleToInteger) {
// In JIT mode VM knows target CPU features at compile time
// and can pick more optimal representation for DoubleToDouble
// conversion. In AOT mode we test if roundsd instruction is
// available at run time and fall back to stub if it isn't.
ASSERT(CompilerState::Current().is_aot());
// In JIT mode without --target-unknown-cpu VM knows target CPU features
// at compile time and can pick more optimal representation
// for DoubleToDouble conversion. In AOT mode and with
// --target-unknown-cpu we test if roundsd instruction is available
// at run time and fall back to stub if it isn't.
ASSERT(CompilerState::Current().is_aot() || FLAG_target_unknown_cpu);
if (FLAG_use_slow_path) {
__ jmp(slow_path->entry_label());
__ Bind(slow_path->exit_label());

View file

@ -940,7 +940,7 @@ bool FlowGraphBuilder::IsRecognizedMethodForFlowGraph(
case MethodRecognizer::kDoubleFloorToInt:
if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
#if defined(TARGET_ARCH_X64)
return CompilerState::Current().is_aot();
return CompilerState::Current().is_aot() || FLAG_target_unknown_cpu;
#elif defined(TARGET_ARCH_ARM64)
return true;
#else

View file

@ -10,6 +10,7 @@
#endif
#include "vm/allocation.h"
#include "vm/flags.h"
#include "vm/simulator.h"
namespace dart {
@ -32,7 +33,7 @@ class HostCPUFeatures : public AllStatic {
}
static bool integer_division_supported() {
DEBUG_ASSERT(initialized_);
return integer_division_supported_;
return integer_division_supported_ && !FLAG_target_unknown_cpu;
}
static bool neon_supported() {
DEBUG_ASSERT(initialized_);

View file

@ -10,6 +10,7 @@
#endif
#include "vm/allocation.h"
#include "vm/flags.h"
#include "vm/simulator.h"
namespace dart {

View file

@ -30,15 +30,15 @@ class HostCPUFeatures : public AllStatic {
}
static bool sse4_1_supported() {
DEBUG_ASSERT(initialized_);
return sse4_1_supported_ && FLAG_use_sse41;
return sse4_1_supported_ && FLAG_use_sse41 && !FLAG_target_unknown_cpu;
}
static bool popcnt_supported() {
DEBUG_ASSERT(initialized_);
return popcnt_supported_;
return popcnt_supported_ && !FLAG_target_unknown_cpu;
}
static bool abm_supported() {
DEBUG_ASSERT(initialized_);
return abm_supported_;
return abm_supported_ && !FLAG_target_unknown_cpu;
}
private:

View file

@ -30,15 +30,15 @@ class HostCPUFeatures : public AllStatic {
}
static bool sse4_1_supported() {
DEBUG_ASSERT(initialized_);
return sse4_1_supported_ && FLAG_use_sse41;
return sse4_1_supported_ && FLAG_use_sse41 && !FLAG_target_unknown_cpu;
}
static bool popcnt_supported() {
DEBUG_ASSERT(initialized_);
return popcnt_supported_;
return popcnt_supported_ && !FLAG_target_unknown_cpu;
}
static bool abm_supported() {
DEBUG_ASSERT(initialized_);
return abm_supported_;
return abm_supported_ && !FLAG_target_unknown_cpu;
}
private:

View file

@ -193,6 +193,8 @@ constexpr bool FLAG_support_il_printer = false;
"needed in the precompiled runtime.") \
P(show_invisible_frames, bool, false, \
"Show invisible frames in stack traces.") \
P(target_unknown_cpu, bool, false, \
"Generate code for a generic CPU, unknown at compile time") \
D(trace_cha, bool, false, "Trace CHA operations") \
R(trace_field_guards, false, bool, false, "Trace changes in field's cids.") \
D(trace_ic, bool, false, "Trace IC handling") \