AIX: workaround the aix FP glibc bug

First CL with initial changes:
https://crrev.com/c/2468618

This CL adds the same set to the wasm interpreter.
We also need to make sure "negation" as well as
"std::abs" are excluded from this fix as they can reverse
the sign bit intentionally.

Change-Id: I115649f55b5290d2529dda3d5592feaff3363b76
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2485246
Reviewed-by: Zhi An Ng <zhin@chromium.org>
Commit-Queue: Milad Fa <mfarazma@redhat.com>
Cr-Commit-Position: refs/heads/master@{#70632}
This commit is contained in:
Milad Fa 2020-10-19 18:58:39 +00:00 committed by Commit Bot
parent 49659a0eed
commit 2f44cf1f86
2 changed files with 36 additions and 10 deletions

View File

@ -414,6 +414,14 @@ bool IsExtreme(float x) {
(abs_x < kSmallFloatThreshold || abs_x > kLargeFloatThreshold);
}
#if V8_OS_AIX
template <typename T>
bool MightReverseSign(T float_op) {
return float_op == static_cast<T>(Negate) ||
float_op == static_cast<T>(std::abs);
}
#endif
WASM_SIMD_TEST(S128Globals) {
WasmRunner<int32_t> r(execution_tier, lower_simd);
// Set up a global to hold input and output vectors.
@ -587,7 +595,8 @@ void RunF32x4UnOpTest(TestExecutionTier execution_tier, LowerSimd lower_simd,
if (!exact && IsExtreme(x)) continue;
float expected = expected_op(x);
#if V8_OS_AIX
expected = FpOpWorkaround<float>(x, expected);
if (!MightReverseSign<FloatUnOp>(expected_op))
expected = FpOpWorkaround<float>(x, expected);
#endif
if (!PlatformCanRepresent(expected)) continue;
r.Call(x);
@ -1180,7 +1189,8 @@ void RunF64x2UnOpTest(TestExecutionTier execution_tier, LowerSimd lower_simd,
if (!exact && IsExtreme(x)) continue;
double expected = expected_op(x);
#if V8_OS_AIX
expected = FpOpWorkaround<double>(x, expected);
if (!MightReverseSign<DoubleUnOp>(expected_op))
expected = FpOpWorkaround<double>(x, expected);
#endif
if (!PlatformCanRepresent(expected)) continue;
r.Call(x);

View File

@ -2085,6 +2085,14 @@ class WasmInterpreterInternals {
return true;
}
template <typename T, T (*float_round_op)(T)>
T AixFpOpWorkaround(T input) {
#if V8_OS_AIX
return FpOpWorkaround<T>(input, float_round_op(input));
#else
return float_round_op(input);
#endif
}
bool ExecuteSimdOp(WasmOpcode opcode, Decoder* decoder, InterpreterCode* code,
pc_t pc, int* const len) {
switch (opcode) {
@ -2251,19 +2259,27 @@ class WasmInterpreterInternals {
UNOP_CASE(F64x2Abs, f64x2, float2, 2, std::abs(a))
UNOP_CASE(F64x2Neg, f64x2, float2, 2, -a)
UNOP_CASE(F64x2Sqrt, f64x2, float2, 2, std::sqrt(a))
UNOP_CASE(F64x2Ceil, f64x2, float2, 2, ceil(a))
UNOP_CASE(F64x2Floor, f64x2, float2, 2, floor(a))
UNOP_CASE(F64x2Trunc, f64x2, float2, 2, trunc(a))
UNOP_CASE(F64x2NearestInt, f64x2, float2, 2, nearbyint(a))
UNOP_CASE(F64x2Ceil, f64x2, float2, 2,
(AixFpOpWorkaround<double, &ceil>(a)))
UNOP_CASE(F64x2Floor, f64x2, float2, 2,
(AixFpOpWorkaround<double, &floor>(a)))
UNOP_CASE(F64x2Trunc, f64x2, float2, 2,
(AixFpOpWorkaround<double, &trunc>(a)))
UNOP_CASE(F64x2NearestInt, f64x2, float2, 2,
(AixFpOpWorkaround<double, &nearbyint>(a)))
UNOP_CASE(F32x4Abs, f32x4, float4, 4, std::abs(a))
UNOP_CASE(F32x4Neg, f32x4, float4, 4, -a)
UNOP_CASE(F32x4Sqrt, f32x4, float4, 4, std::sqrt(a))
UNOP_CASE(F32x4RecipApprox, f32x4, float4, 4, base::Recip(a))
UNOP_CASE(F32x4RecipSqrtApprox, f32x4, float4, 4, base::RecipSqrt(a))
UNOP_CASE(F32x4Ceil, f32x4, float4, 4, ceilf(a))
UNOP_CASE(F32x4Floor, f32x4, float4, 4, floorf(a))
UNOP_CASE(F32x4Trunc, f32x4, float4, 4, truncf(a))
UNOP_CASE(F32x4NearestInt, f32x4, float4, 4, nearbyintf(a))
UNOP_CASE(F32x4Ceil, f32x4, float4, 4,
(AixFpOpWorkaround<float, &ceilf>(a)))
UNOP_CASE(F32x4Floor, f32x4, float4, 4,
(AixFpOpWorkaround<float, &floorf>(a)))
UNOP_CASE(F32x4Trunc, f32x4, float4, 4,
(AixFpOpWorkaround<float, &truncf>(a)))
UNOP_CASE(F32x4NearestInt, f32x4, float4, 4,
(AixFpOpWorkaround<float, &nearbyintf>(a)))
UNOP_CASE(I64x2Neg, i64x2, int2, 2, base::NegateWithWraparound(a))
UNOP_CASE(I32x4Neg, i32x4, int4, 4, base::NegateWithWraparound(a))
UNOP_CASE(I32x4Abs, i32x4, int4, 4, std::abs(a))