Commit 3844a6bd authored by Ng Zhi An's avatar Ng Zhi An Committed by Commit Bot

[x64][ia32] Reconcile supported extensions

This is similar in spirit to https://crrev.com/c/2808621, which is to
ensure that no matter what combination of --[no-]enable-{extension} flag
is passed, we end up with a set of supported extensions that make sense.

The 2 rules are:

- If a newer extension is supported (SSE4_2), older extensions are
supported (SSE4_1, SSSE3, SSE3),
- If an older extension is not supported (SSE4_1), new extensions are
not supported (SSE4_2, AVX)

Tests have been added to both ia32 and x64 to check that we follow these
above 2 rules.

We change the ProbeImpl to have a reconciliation step to ensure that we
stick to the 2 rules.

E.g. if --enable-avx --no-enable-sse4-2, we will first set AVX to
supported, then in the second step, fix-up AVX to unsupported. In this
sense, the --no version of the flags take priority. This more accurately
follows the intention of the flags.

Bug: chromium:1195579
Change-Id: I0390f24de9d203fe6bbd4cc02a23771a1f052618
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2818570
Commit-Queue: Zhi An Ng <zhin@chromium.org>
Reviewed-by: 's avatarMichael Achenbach <machenbach@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73942}
parent 7cc6127b
...@@ -109,6 +109,9 @@ class V8_EXPORT_PRIVATE CpuFeatures : public AllStatic { ...@@ -109,6 +109,9 @@ class V8_EXPORT_PRIVATE CpuFeatures : public AllStatic {
return (supported_ & (1u << f)) != 0; return (supported_ & (1u << f)) != 0;
} }
static void SetSupported(CpuFeature f) { supported_ |= 1u << f; }
static void SetUnsupported(CpuFeature f) { supported_ &= ~(1u << f); }
static bool SupportsWasmSimd128(); static bool SupportsWasmSimd128();
static inline bool SupportsOptimizer(); static inline bool SupportsOptimizer();
......
...@@ -138,31 +138,38 @@ void CpuFeatures::ProbeImpl(bool cross_compile) { ...@@ -138,31 +138,38 @@ void CpuFeatures::ProbeImpl(bool cross_compile) {
// Only use statically determined features for cross compile (snapshot). // Only use statically determined features for cross compile (snapshot).
if (cross_compile) return; if (cross_compile) return;
if (cpu.has_sse42() && FLAG_enable_sse4_2) supported_ |= 1u << SSE4_2; if (cpu.has_sse42()) SetSupported(SSE4_2);
if (cpu.has_sse41() && FLAG_enable_sse4_1) supported_ |= 1u << SSE4_1; if (cpu.has_sse41()) SetSupported(SSE4_1);
if (cpu.has_ssse3() && FLAG_enable_ssse3) supported_ |= 1u << SSSE3; if (cpu.has_ssse3()) SetSupported(SSSE3);
if (cpu.has_sse3() && FLAG_enable_sse3) supported_ |= 1u << SSE3; if (cpu.has_sse3()) SetSupported(SSE3);
if (cpu.has_avx() && FLAG_enable_avx && cpu.has_osxsave() && if (cpu.has_avx() && cpu.has_osxsave() && OSHasAVXSupport()) {
OSHasAVXSupport()) { SetSupported(AVX);
supported_ |= 1u << AVX; if (cpu.has_avx2()) SetSupported(AVX2);
if (cpu.has_fma3()) SetSupported(FMA3);
} }
if (cpu.has_avx2() && FLAG_enable_avx2 && IsSupported(AVX)) {
supported_ |= 1u << AVX2; if (cpu.has_bmi1() && FLAG_enable_bmi1) SetSupported(BMI1);
} if (cpu.has_bmi2() && FLAG_enable_bmi2) SetSupported(BMI2);
if (cpu.has_fma3() && FLAG_enable_fma3 && cpu.has_osxsave() && if (cpu.has_lzcnt() && FLAG_enable_lzcnt) SetSupported(LZCNT);
OSHasAVXSupport()) { if (cpu.has_popcnt() && FLAG_enable_popcnt) SetSupported(POPCNT);
supported_ |= 1u << FMA3;
}
if (cpu.has_bmi1() && FLAG_enable_bmi1) supported_ |= 1u << BMI1;
if (cpu.has_bmi2() && FLAG_enable_bmi2) supported_ |= 1u << BMI2;
if (cpu.has_lzcnt() && FLAG_enable_lzcnt) supported_ |= 1u << LZCNT;
if (cpu.has_popcnt() && FLAG_enable_popcnt) supported_ |= 1u << POPCNT;
if (strcmp(FLAG_mcpu, "auto") == 0) { if (strcmp(FLAG_mcpu, "auto") == 0) {
if (cpu.is_atom()) supported_ |= 1u << ATOM; if (cpu.is_atom()) SetSupported(ATOM);
} else if (strcmp(FLAG_mcpu, "atom") == 0) { } else if (strcmp(FLAG_mcpu, "atom") == 0) {
supported_ |= 1u << ATOM; SetSupported(ATOM);
} }
// Ensure that supported cpu features make sense. E.g. it is wrong to support
// AVX but not SSE4_2, if we have --enable-avx and --no-enable-sse4-2, the
// code above would set AVX to supported, and SSE4_2 to unsupported, then the
// checks below will set AVX to unsupported.
if (!FLAG_enable_sse3) SetUnsupported(SSE3);
if (!FLAG_enable_ssse3 || !IsSupported(SSE3)) SetUnsupported(SSSE3);
if (!FLAG_enable_sse4_1 || !IsSupported(SSSE3)) SetUnsupported(SSE4_1);
if (!FLAG_enable_sse4_2 || !IsSupported(SSE4_1)) SetUnsupported(SSE4_2);
if (!FLAG_enable_avx || !IsSupported(SSE4_2)) SetUnsupported(AVX);
if (!FLAG_enable_avx2 || !IsSupported(AVX)) SetUnsupported(AVX2);
if (!FLAG_enable_fma3 || !IsSupported(AVX)) SetUnsupported(FMA3);
// Set a static value on whether Simd is supported. // Set a static value on whether Simd is supported.
// This variable is only used for certain archs to query SupportWasmSimd128() // This variable is only used for certain archs to query SupportWasmSimd128()
// at runtime in builtins using an extern ref. Other callers should use // at runtime in builtins using an extern ref. Other callers should use
......
...@@ -86,37 +86,40 @@ void CpuFeatures::ProbeImpl(bool cross_compile) { ...@@ -86,37 +86,40 @@ void CpuFeatures::ProbeImpl(bool cross_compile) {
// Only use statically determined features for cross compile (snapshot). // Only use statically determined features for cross compile (snapshot).
if (cross_compile) return; if (cross_compile) return;
if (cpu.has_sse42()) SetSupported(SSE4_2);
if (cpu.has_sse42() && FLAG_enable_sse4_2) supported_ |= 1u << SSE4_2; if (cpu.has_sse41()) SetSupported(SSE4_1);
if (cpu.has_sse41() && FLAG_enable_sse4_1) { if (cpu.has_ssse3()) SetSupported(SSSE3);
supported_ |= 1u << SSE4_1; if (cpu.has_sse3()) SetSupported(SSE3);
supported_ |= 1u << SSSE3; if (cpu.has_avx() && cpu.has_osxsave() && OSHasAVXSupport()) {
SetSupported(AVX);
if (cpu.has_avx2()) SetSupported(AVX2);
if (cpu.has_fma3()) SetSupported(FMA3);
} }
if (cpu.has_ssse3() && FLAG_enable_ssse3) supported_ |= 1u << SSSE3;
if (cpu.has_sse3() && FLAG_enable_sse3) supported_ |= 1u << SSE3;
// SAHF is not generally available in long mode. // SAHF is not generally available in long mode.
if (cpu.has_sahf() && FLAG_enable_sahf) supported_ |= 1u << SAHF; if (cpu.has_sahf() && FLAG_enable_sahf) SetSupported(SAHF);
if (cpu.has_avx() && FLAG_enable_avx && cpu.has_osxsave() && if (cpu.has_bmi1() && FLAG_enable_bmi1) SetSupported(BMI1);
OSHasAVXSupport()) { if (cpu.has_bmi2() && FLAG_enable_bmi2) SetSupported(BMI2);
supported_ |= 1u << AVX; if (cpu.has_lzcnt() && FLAG_enable_lzcnt) SetSupported(LZCNT);
} if (cpu.has_popcnt() && FLAG_enable_popcnt) SetSupported(POPCNT);
if (cpu.has_avx2() && FLAG_enable_avx2 && IsSupported(AVX)) {
supported_ |= 1u << AVX2;
}
if (cpu.has_fma3() && FLAG_enable_fma3 && cpu.has_osxsave() &&
OSHasAVXSupport()) {
supported_ |= 1u << FMA3;
}
if (cpu.has_bmi1() && FLAG_enable_bmi1) supported_ |= 1u << BMI1;
if (cpu.has_bmi2() && FLAG_enable_bmi2) supported_ |= 1u << BMI2;
if (cpu.has_lzcnt() && FLAG_enable_lzcnt) supported_ |= 1u << LZCNT;
if (cpu.has_popcnt() && FLAG_enable_popcnt) supported_ |= 1u << POPCNT;
if (strcmp(FLAG_mcpu, "auto") == 0) { if (strcmp(FLAG_mcpu, "auto") == 0) {
if (cpu.is_atom()) supported_ |= 1u << ATOM; if (cpu.is_atom()) SetSupported(ATOM);
} else if (strcmp(FLAG_mcpu, "atom") == 0) { } else if (strcmp(FLAG_mcpu, "atom") == 0) {
supported_ |= 1u << ATOM; SetSupported(ATOM);
} }
// Ensure that supported cpu features make sense. E.g. it is wrong to support
// AVX but not SSE4_2, if we have --enable-avx and --no-enable-sse4-2, the
// code above would set AVX to supported, and SSE4_2 to unsupported, then the
// checks below will set AVX to unsupported.
if (!FLAG_enable_sse3) SetUnsupported(SSE3);
if (!FLAG_enable_ssse3 || !IsSupported(SSE3)) SetUnsupported(SSSE3);
if (!FLAG_enable_sse4_1 || !IsSupported(SSSE3)) SetUnsupported(SSE4_1);
if (!FLAG_enable_sse4_2 || !IsSupported(SSE4_1)) SetUnsupported(SSE4_2);
if (!FLAG_enable_avx || !IsSupported(SSE4_2)) SetUnsupported(AVX);
if (!FLAG_enable_avx2 || !IsSupported(AVX)) SetUnsupported(AVX2);
if (!FLAG_enable_fma3 || !IsSupported(AVX)) SetUnsupported(FMA3);
// Set a static value on whether Simd is supported. // Set a static value on whether Simd is supported.
// This variable is only used for certain archs to query SupportWasmSimd128() // This variable is only used for certain archs to query SupportWasmSimd128()
// at runtime in builtins using an extern ref. Other callers should use // at runtime in builtins using an extern ref. Other callers should use
......
...@@ -1550,6 +1550,35 @@ TEST(DeoptExitSizeIsFixed) { ...@@ -1550,6 +1550,35 @@ TEST(DeoptExitSizeIsFixed) {
} }
} }
TEST(CpuFeatures_ProbeImpl) {
// Support for a newer extension implies support for the older extensions.
CHECK_IMPLIES(CpuFeatures::IsSupported(FMA3), CpuFeatures::IsSupported(AVX));
CHECK_IMPLIES(CpuFeatures::IsSupported(AVX2), CpuFeatures::IsSupported(AVX));
CHECK_IMPLIES(CpuFeatures::IsSupported(AVX),
CpuFeatures::IsSupported(SSE4_2));
CHECK_IMPLIES(CpuFeatures::IsSupported(SSE4_2),
CpuFeatures::IsSupported(SSE4_1));
CHECK_IMPLIES(CpuFeatures::IsSupported(SSE4_1),
CpuFeatures::IsSupported(SSSE3));
CHECK_IMPLIES(CpuFeatures::IsSupported(SSSE3),
CpuFeatures::IsSupported(SSE3));
// Check the reverse, if an older extension is not supported, a newer
// extension cannot be supported.
CHECK_IMPLIES(!CpuFeatures::IsSupported(SSE3),
!CpuFeatures::IsSupported(SSSE3));
CHECK_IMPLIES(!CpuFeatures::IsSupported(SSSE3),
!CpuFeatures::IsSupported(SSE4_1));
CHECK_IMPLIES(!CpuFeatures::IsSupported(SSE4_1),
!CpuFeatures::IsSupported(SSE4_2));
CHECK_IMPLIES(!CpuFeatures::IsSupported(SSE4_2),
!CpuFeatures::IsSupported(AVX));
CHECK_IMPLIES(!CpuFeatures::IsSupported(AVX),
!CpuFeatures::IsSupported(AVX2));
CHECK_IMPLIES(!CpuFeatures::IsSupported(AVX),
!CpuFeatures::IsSupported(FMA3));
}
#undef __ #undef __
} // namespace internal } // namespace internal
......
...@@ -2521,6 +2521,35 @@ TEST(AssemblerX64vmovups) { ...@@ -2521,6 +2521,35 @@ TEST(AssemblerX64vmovups) {
CHECK_EQ(-1.5, f.Call(1.5, -1.5)); CHECK_EQ(-1.5, f.Call(1.5, -1.5));
} }
TEST(CpuFeatures_ProbeImpl) {
// Support for a newer extension implies support for the older extensions.
CHECK_IMPLIES(CpuFeatures::IsSupported(FMA3), CpuFeatures::IsSupported(AVX));
CHECK_IMPLIES(CpuFeatures::IsSupported(AVX2), CpuFeatures::IsSupported(AVX));
CHECK_IMPLIES(CpuFeatures::IsSupported(AVX),
CpuFeatures::IsSupported(SSE4_2));
CHECK_IMPLIES(CpuFeatures::IsSupported(SSE4_2),
CpuFeatures::IsSupported(SSE4_1));
CHECK_IMPLIES(CpuFeatures::IsSupported(SSE4_1),
CpuFeatures::IsSupported(SSSE3));
CHECK_IMPLIES(CpuFeatures::IsSupported(SSSE3),
CpuFeatures::IsSupported(SSE3));
// Check the reverse, if an older extension is not supported, a newer
// extension cannot be supported.
CHECK_IMPLIES(!CpuFeatures::IsSupported(SSE3),
!CpuFeatures::IsSupported(SSSE3));
CHECK_IMPLIES(!CpuFeatures::IsSupported(SSSE3),
!CpuFeatures::IsSupported(SSE4_1));
CHECK_IMPLIES(!CpuFeatures::IsSupported(SSE4_1),
!CpuFeatures::IsSupported(SSE4_2));
CHECK_IMPLIES(!CpuFeatures::IsSupported(SSE4_2),
!CpuFeatures::IsSupported(AVX));
CHECK_IMPLIES(!CpuFeatures::IsSupported(AVX),
!CpuFeatures::IsSupported(AVX2));
CHECK_IMPLIES(!CpuFeatures::IsSupported(AVX),
!CpuFeatures::IsSupported(FMA3));
}
#undef __ #undef __
} // namespace internal } // namespace internal
......
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