[wasm] Fix SIMD boolean reductions on Intel

- Both AllTrue/AnyTrue values should return boolean 0/1
   instead of 0xffffffff to match Spec/Toolchain
 - Fix AllTrue implementation to be correct
 - Add unit tests to spot check return values as the
   cumulative test can coerce some return values to True/False

Change-Id: I84eb73c915414c9ec290e73f1306404ceff729f0
Bug: v8:8636
Reviewed-on: https://chromium-review.googlesource.com/c/1404197
Reviewed-by: Bill Budge <bbudge@chromium.org>
Commit-Queue: Deepti Gandluri <gdeepti@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58715}
This commit is contained in:
Deepti Gandluri 2019-01-10 08:18:41 -08:00 committed by Commit Bot
parent ef12b47b59
commit 8f83fd0a55
3 changed files with 57 additions and 24 deletions

View File

@ -3604,7 +3604,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
XMMRegister src = i.InputSimd128Register(0);
Register tmp = i.TempRegister(0);
__ xor_(tmp, tmp);
__ mov(dst, Immediate(-1));
__ mov(dst, Immediate(1));
__ Ptest(src, src);
__ cmov(zero, dst, tmp);
break;
@ -3615,18 +3615,10 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
Register dst = i.OutputRegister();
Operand src = i.InputOperand(0);
Register tmp = i.TempRegister(0);
__ mov(tmp, Immediate(-1));
__ mov(tmp, Immediate(1));
__ xor_(dst, dst);
// Compare all src lanes to false.
__ Pxor(kScratchDoubleReg, kScratchDoubleReg);
if (arch_opcode == kIA32S1x4AllTrue) {
__ Pcmpeqd(kScratchDoubleReg, src);
} else if (arch_opcode == kIA32S1x8AllTrue) {
__ Pcmpeqw(kScratchDoubleReg, src);
} else {
__ Pcmpeqb(kScratchDoubleReg, src);
}
// If kScratchDoubleReg is all zero, none of src lanes are false.
__ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
__ pxor(kScratchDoubleReg, src);
__ Ptest(kScratchDoubleReg, kScratchDoubleReg);
__ cmov(zero, dst, tmp);
break;

View File

@ -3219,7 +3219,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
XMMRegister src = i.InputSimd128Register(0);
Register tmp = i.TempRegister(0);
__ xorq(tmp, tmp);
__ movq(dst, Immediate(-1));
__ movq(dst, Immediate(1));
__ ptest(src, src);
__ cmovq(zero, dst, tmp);
break;
@ -3231,18 +3231,10 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
Register dst = i.OutputRegister();
XMMRegister src = i.InputSimd128Register(0);
Register tmp = i.TempRegister(0);
__ movq(tmp, Immediate(-1));
__ movq(tmp, Immediate(1));
__ xorq(dst, dst);
// Compare all src lanes to false.
__ pxor(kScratchDoubleReg, kScratchDoubleReg);
if (arch_opcode == kX64S1x4AllTrue) {
__ pcmpeqd(kScratchDoubleReg, src);
} else if (arch_opcode == kX64S1x8AllTrue) {
__ pcmpeqw(kScratchDoubleReg, src);
} else {
__ pcmpeqb(kScratchDoubleReg, src);
}
// If kScratchDoubleReg is all zero, none of src lanes are false.
__ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
__ pxor(kScratchDoubleReg, src);
__ ptest(kScratchDoubleReg, kScratchDoubleReg);
__ cmovq(zero, dst, tmp);
break;

View File

@ -452,6 +452,15 @@ WASM_SIMD_TEST(F32x4ReplaceLane) {
} \
void RunWasm_##name##_Impl(LowerSimd lower_simd, ExecutionTier execution_tier)
#define WASM_SIMD_TEST_WITHOUT_LOWERING(name) \
void RunWasm_##name##_Impl(LowerSimd lower_simd, \
ExecutionTier execution_tier); \
TEST(RunWasm_##name##_turbofan) { \
EXPERIMENTAL_FLAG_SCOPE(simd); \
RunWasm_##name##_Impl(kNoLowerSimd, ExecutionTier::kOptimized); \
} \
void RunWasm_##name##_Impl(LowerSimd lower_simd, ExecutionTier execution_tier)
// Tests both signed and unsigned conversion.
// v8:8425 tracks this test being enabled in the interpreter.
WASM_SIMD_COMPILED_TEST(F32x4ConvertI32x4) {
@ -2328,6 +2337,43 @@ WASM_SIMD_COMPILED_TEST(SimdLoadStoreLoad) {
}
}
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32
// TODO(gdeepti): Enable these tests for ARM/ARM64
// V8:8665 - Tracking but to enable reduction tests in the interpreter,
// and for SIMD lowering
#define WASM_SIMD_ANYTRUE_TEST(format, lanes, max) \
WASM_SIMD_TEST_WITHOUT_LOWERING(S##format##AnyTrue) { \
WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd); \
byte simd = r.AllocateLocal(kWasmS128); \
BUILD( \
r, \
WASM_SET_LOCAL(simd, WASM_SIMD_I##format##_SPLAT(WASM_GET_LOCAL(0))), \
WASM_SIMD_UNOP(kExprS1x##lanes##AnyTrue, WASM_GET_LOCAL(simd))); \
DCHECK_EQ(1, r.Call(max)); \
DCHECK_EQ(1, r.Call(5)); \
DCHECK_EQ(0, r.Call(0)); \
}
WASM_SIMD_ANYTRUE_TEST(32x4, 4, 0xffffffff);
WASM_SIMD_ANYTRUE_TEST(16x8, 8, 0xffff);
WASM_SIMD_ANYTRUE_TEST(8x16, 16, 0xff);
#define WASM_SIMD_ALLTRUE_TEST(format, lanes, max) \
WASM_SIMD_TEST_WITHOUT_LOWERING(S##format##AllTrue) { \
WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd); \
byte simd = r.AllocateLocal(kWasmS128); \
BUILD( \
r, \
WASM_SET_LOCAL(simd, WASM_SIMD_I##format##_SPLAT(WASM_GET_LOCAL(0))), \
WASM_SIMD_UNOP(kExprS1x##lanes##AllTrue, WASM_GET_LOCAL(simd))); \
DCHECK_EQ(1, r.Call(max)); \
DCHECK_EQ(0, r.Call(21)); \
DCHECK_EQ(0, r.Call(0)); \
}
WASM_SIMD_ALLTRUE_TEST(32x4, 4, 0xffffffff);
WASM_SIMD_ALLTRUE_TEST(16x8, 8, 0xffff);
WASM_SIMD_ALLTRUE_TEST(8x16, 16, 0xff);
#endif // V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32
#undef WASM_SIMD_TEST
#undef WASM_SIMD_CHECK_LANE
#undef WASM_SIMD_CHECK4
@ -2368,6 +2414,9 @@ WASM_SIMD_COMPILED_TEST(SimdLoadStoreLoad) {
#undef WASM_SIMD_NON_CANONICAL_SELECT_TEST
#undef WASM_SIMD_COMPILED_TEST
#undef WASM_SIMD_BOOL_REDUCTION_TEST
#undef WASM_SIMD_TEST_WITHOUT_LOWERING
#undef WASM_SIMD_ANYTRUE_TEST
#undef WASM_SIMD_ALLTRUE_TEST
} // namespace test_run_wasm_simd
} // namespace wasm