diff --git a/js/src/jit-test/tests/wasm/basic-integer.js b/js/src/jit-test/tests/wasm/basic-integer.js index 815195ee8992..ab9929ad42b9 100644 --- a/js/src/jit-test/tests/wasm/basic-integer.js +++ b/js/src/jit-test/tests/wasm/basic-integer.js @@ -139,6 +139,11 @@ testComparison32('gt_u', 40, 40, 0); testComparison32('ge_s', 40, 40, 1); testComparison32('ge_u', 40, 40, 1); +// Test MTest's GVN branch inversion. +var testTrunc = wasmEvalText(`(module (func (param f32) (result i32) (if (i32.eqz (i32.trunc_s/f32 (get_local 0))) (i32.const 0) (i32.const 1))) (export "" 0))`); +assertEq(testTrunc(0), 0); +assertEq(testTrunc(13.37), 1); + if (hasI64()) { setJitCompilerOption('wasm.test-mode', 1); @@ -253,6 +258,11 @@ if (hasI64()) { testUnary('i64', 'popcnt', -1, 64); testUnary('i64', 'popcnt', 0, 0); + // Test MTest's GVN branch inversion. + var testTrunc = wasmEvalText(`(module (func (param f32) (result i32) (if (i64.eqz (i64.trunc_s/f32 (get_local 0))) (i32.const 0) (i32.const 1))) (export "" 0))`); + assertEq(testTrunc(0), 0); + assertEq(testTrunc(13.37), 1); + testI64Eqz(40, 0); testI64Eqz(0, 1); diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp index c7758901d994..4ef619626d36 100644 --- a/js/src/jit/Lowering.cpp +++ b/js/src/jit/Lowering.cpp @@ -936,6 +936,9 @@ LIRGenerator::visitTest(MTest* test) case MIRType::Boolean: add(new(alloc()) LTestIAndBranch(useRegister(opd), ifTrue, ifFalse)); break; + case MIRType::Int64: + add(new(alloc()) LTestI64AndBranch(useInt64Register(opd), ifTrue, ifFalse)); + break; default: MOZ_CRASH("Bad type"); } diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index a5fdc14af51a..395b5963ef7b 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -4568,10 +4568,8 @@ MNot::foldsTo(TempAllocator& alloc) if (MConstant* inputConst = input()->maybeConstantValue()) { bool b; if (inputConst->valueToBoolean(&b)) { - if (type() == MIRType::Int32) + if (type() == MIRType::Int32 || type() == MIRType::Int64) return MConstant::New(alloc, Int32Value(!b)); - if (type() == MIRType::Int64) - return MConstant::NewInt64(alloc, int64_t(!b)); return MConstant::New(alloc, BooleanValue(!b)); } } diff --git a/js/src/jit/shared/LIR-shared.h b/js/src/jit/shared/LIR-shared.h index 41301ca556ea..6eb350d469e6 100644 --- a/js/src/jit/shared/LIR-shared.h +++ b/js/src/jit/shared/LIR-shared.h @@ -2258,6 +2258,27 @@ class LTestIAndBranch : public LControlInstructionHelper<2, 1, 0> } }; +// Takes in an int64 input and tests it for truthiness. +class LTestI64AndBranch : public LControlInstructionHelper<2, INT64_PIECES, 0> +{ + public: + LIR_HEADER(TestI64AndBranch) + + LTestI64AndBranch(const LInt64Allocation& in, MBasicBlock* ifTrue, MBasicBlock* ifFalse) + { + setInt64Operand(0, in); + setSuccessor(0, ifTrue); + setSuccessor(1, ifFalse); + } + + MBasicBlock* ifTrue() const { + return getSuccessor(0); + } + MBasicBlock* ifFalse() const { + return getSuccessor(1); + } +}; + // Takes in either an integer or boolean input and tests it for truthiness. class LTestDAndBranch : public LControlInstructionHelper<2, 1, 0> { diff --git a/js/src/jit/shared/LOpcodes-shared.h b/js/src/jit/shared/LOpcodes-shared.h index 5eb400d43949..b3a37507921b 100644 --- a/js/src/jit/shared/LOpcodes-shared.h +++ b/js/src/jit/shared/LOpcodes-shared.h @@ -116,6 +116,7 @@ _(Throw) \ _(Phi) \ _(TestIAndBranch) \ + _(TestI64AndBranch) \ _(TestDAndBranch) \ _(TestFAndBranch) \ _(TestVAndBranch) \ diff --git a/js/src/jit/x64/CodeGenerator-x64.cpp b/js/src/jit/x64/CodeGenerator-x64.cpp index 9b1bc8edb228..1418756a69e4 100644 --- a/js/src/jit/x64/CodeGenerator-x64.cpp +++ b/js/src/jit/x64/CodeGenerator-x64.cpp @@ -1391,3 +1391,11 @@ CodeGeneratorX64::visitPopcntI64(LPopcntI64* lir) masm.popcnt64(input, output, temp); } + +void +CodeGeneratorX64::visitTestI64AndBranch(LTestI64AndBranch* lir) +{ + Register input = ToRegister(lir->input()); + masm.testq(input, input); + emitBranch(Assembler::NonZero, lir->ifTrue(), lir->ifFalse()); +} diff --git a/js/src/jit/x64/CodeGenerator-x64.h b/js/src/jit/x64/CodeGenerator-x64.h index c6c93cdbf447..1fa0447c9be1 100644 --- a/js/src/jit/x64/CodeGenerator-x64.h +++ b/js/src/jit/x64/CodeGenerator-x64.h @@ -80,6 +80,7 @@ class CodeGeneratorX64 : public CodeGeneratorX86Shared void visitAsmJSUInt32ToFloat32(LAsmJSUInt32ToFloat32* lir); void visitAsmReinterpretFromI64(LAsmReinterpretFromI64* lir); void visitAsmReinterpretToI64(LAsmReinterpretToI64* lir); + void visitTestI64AndBranch(LTestI64AndBranch* lir); void visitWasmTruncateToInt32(LWasmTruncateToInt32* lir); }; diff --git a/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp b/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp index 677183f640f5..0ff3fbe3b475 100644 --- a/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp +++ b/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp @@ -81,10 +81,8 @@ CodeGeneratorX86Shared::visitFloat32(LFloat32* ins) void CodeGeneratorX86Shared::visitTestIAndBranch(LTestIAndBranch* test) { - const LAllocation* opd = test->input(); - - // Test the operand - masm.test32(ToRegister(opd), ToRegister(opd)); + Register input = ToRegister(test->input()); + masm.test32(input, input); emitBranch(Assembler::NonZero, test->ifTrue(), test->ifFalse()); }