diff --git a/js/src/jit-test/tests/SIMD/swizzle.js b/js/src/jit-test/tests/SIMD/swizzle.js new file mode 100644 index 000000000000..8eb365e829cf --- /dev/null +++ b/js/src/jit-test/tests/SIMD/swizzle.js @@ -0,0 +1,71 @@ +if (!this.hasOwnProperty("SIMD")) + quit(); + +load(libdir + 'simd.js'); + +setJitCompilerOption("ion.warmup.trigger", 50); + +function f() { + var i4 = SIMD.int32x4(1, 2, 3, 4); + + var leet = Math.fround(13.37); + var f4 = SIMD.float32x4(-.5, -0, Infinity, leet); + + var compI = [ + [1,2,3,4], + [2,3,4,1], + [3,4,1,2], + [4,1,2,3] + ]; + + var compF = [ + [-.5, -0, Infinity, leet], + [-0, Infinity, leet, -.5], + [Infinity, leet, -.5, -0], + [leet, -.5, -0, Infinity] + ]; + + for (var i = 0; i < 150; i++) { + // Variable lanes + var r = SIMD.float32x4.swizzle(f4, i % 4, (i + 1) % 4, (i + 2) % 4, (i + 3) % 4); + assertEqX4(r, compF[i % 4]); + + // Constant lanes + assertEqX4(SIMD.float32x4.swizzle(f4, 3, 2, 1, 0), [leet, Infinity, -0, -.5]); + + // Variable lanes + var r = SIMD.int32x4.swizzle(i4, i % 4, (i + 1) % 4, (i + 2) % 4, (i + 3) % 4); + assertEqX4(r, compI[i % 4]); + + // Constant lanes + assertEqX4(SIMD.int32x4.swizzle(i4, 3, 2, 1, 0), [4, 3, 2, 1]); + } +} + +function testBailouts(uglyDuckling) { + var i4 = SIMD.int32x4(1, 2, 3, 4); + for (var i = 0; i < 150; i++) { + // Test bailouts + var value = i == 149 ? uglyDuckling : 0; + var caught = false; + try { + assertEqX4(SIMD.int32x4.swizzle(i4, value, 3, 2, 0), [1, 4, 3, 1]); + } catch(e) { + print(e); + caught = true; + assertEq(i, 149); + assertEq(e instanceof TypeError, true); + } + assertEq(i < 149 || caught, true); + } +} + +f(); +testBailouts(-1); +testBailouts(4); +testBailouts(2.5); +testBailouts(undefined); +testBailouts(null); +testBailouts({}); +testBailouts('one'); +testBailouts(true); diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp index 333893c627fb..be54c75a3a57 100644 --- a/js/src/jit/Lowering.cpp +++ b/js/src/jit/Lowering.cpp @@ -3963,10 +3963,12 @@ LIRGenerator::visitSimdGeneralSwizzle(MSimdGeneralSwizzle *ins) if (ins->input()->type() == MIRType_Int32x4) { LSimdGeneralSwizzleI *lir = new (alloc()) LSimdGeneralSwizzleI(useRegister(ins->input()), lanesUses, temp()); + assignSnapshot(lir, Bailout_BoundsCheck); define(lir, ins); } else if (ins->input()->type() == MIRType_Float32x4) { LSimdGeneralSwizzleF *lir = new (alloc()) LSimdGeneralSwizzleF(useRegister(ins->input()), lanesUses, temp()); + assignSnapshot(lir, Bailout_BoundsCheck); define(lir, ins); } else { MOZ_CRASH("Unknown SIMD kind when getting lane"); diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp index 57b36da1cb78..364c56c6fa46 100644 --- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -354,13 +354,14 @@ IonBuilder::inlineNativeCall(CallInfo &callInfo, JSFunction *target) if (native == js::simd_int32x4_swizzle) return inlineSimdSwizzle(callInfo, native, SimdTypeDescr::TYPE_INT32); + if (native == js::simd_float32x4_swizzle) + return inlineSimdSwizzle(callInfo, native, SimdTypeDescr::TYPE_FLOAT32); if (native == js::simd_int32x4_load) return inlineSimdLoad(callInfo, native, SimdTypeDescr::TYPE_INT32); if (native == js::simd_float32x4_load) return inlineSimdLoad(callInfo, native, SimdTypeDescr::TYPE_FLOAT32); - if (native == js::simd_int32x4_store) return inlineSimdStore(callInfo, native, SimdTypeDescr::TYPE_INT32); if (native == js::simd_float32x4_store) diff --git a/js/src/jit/TypePolicy.cpp b/js/src/jit/TypePolicy.cpp index d5333ff254c8..a745f045937f 100644 --- a/js/src/jit/TypePolicy.cpp +++ b/js/src/jit/TypePolicy.cpp @@ -800,7 +800,7 @@ SimdSwizzlePolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins) if (in->type() == MIRType_Int32) continue; - MInstruction *replace = MTruncateToInt32::New(alloc, in); + MInstruction *replace = MToInt32::New(alloc, in, MacroAssembler::IntConversion_NumbersOnly); ins->block()->insertBefore(ins, replace); ins->replaceOperand(i + 1, replace); if (!replace->typePolicy()->adjustInputs(alloc, replace)) diff --git a/js/src/jit/shared/CodeGenerator-x86-shared.cpp b/js/src/jit/shared/CodeGenerator-x86-shared.cpp index 7f14e8aa8170..6de9e4037a3f 100644 --- a/js/src/jit/shared/CodeGenerator-x86-shared.cpp +++ b/js/src/jit/shared/CodeGenerator-x86-shared.cpp @@ -2392,19 +2392,14 @@ CodeGeneratorX86Shared::visitSimdGeneralSwizzleI(LSimdGeneralSwizzleI *ins) masm.storeAlignedInt32x4(input, Address(StackPointer, Simd128DataSize)); + Label bail; + for (size_t i = 0; i < 4; i++) { Operand lane = ToOperand(ins->lane(i)); - Label go, join; - masm.cmp32(lane, Imm32(4)); - masm.j(Assembler::Below, &go); + masm.cmp32(lane, Imm32(3)); + masm.j(Assembler::Above, &bail); - { - masm.store32(Imm32(0), Address(StackPointer, i * sizeof(int32_t))); - masm.jump(&join); - } - - masm.bind(&go); if (lane.kind() == Operand::REG) { masm.load32(Operand(StackPointer, ToRegister(ins->lane(i)), TimesFour, Simd128DataSize), temp); @@ -2414,12 +2409,22 @@ CodeGeneratorX86Shared::visitSimdGeneralSwizzleI(LSimdGeneralSwizzleI *ins) } masm.store32(temp, Address(StackPointer, i * sizeof(int32_t))); - masm.bind(&join); } FloatRegister output = ToFloatRegister(ins->output()); masm.loadAlignedInt32x4(Address(StackPointer, 0), output); + Label join; + masm.jump(&join); + + { + masm.bind(&bail); + masm.setFramePushed(masm.framePushed() + Simd128DataSize * 2); + masm.freeStack(Simd128DataSize * 2); + bailout(ins->snapshot()); + } + + masm.bind(&join); masm.freeStack(Simd128DataSize * 2); } @@ -2434,20 +2439,14 @@ CodeGeneratorX86Shared::visitSimdGeneralSwizzleF(LSimdGeneralSwizzleF *ins) masm.storeAlignedFloat32x4(input, Address(StackPointer, Simd128DataSize)); + Label bail; + for (size_t i = 0; i < 4; i++) { Operand lane = ToOperand(ins->lane(i)); - Label go, join; - masm.cmp32(lane, Imm32(4)); - masm.j(Assembler::Below, &go); + masm.cmp32(lane, Imm32(3)); + masm.j(Assembler::Above, &bail); - { - masm.loadConstantFloat32(float(GenericNaN()), ScratchFloat32Reg); - masm.storeFloat32(ScratchFloat32Reg, Address(StackPointer, i * sizeof(int32_t))); - masm.jump(&join); - } - - masm.bind(&go); if (lane.kind() == Operand::REG) { masm.loadFloat32(Operand(StackPointer, ToRegister(ins->lane(i)), TimesFour, Simd128DataSize), ScratchFloat32Reg); @@ -2457,12 +2456,22 @@ CodeGeneratorX86Shared::visitSimdGeneralSwizzleF(LSimdGeneralSwizzleF *ins) } masm.storeFloat32(ScratchFloat32Reg, Address(StackPointer, i * sizeof(int32_t))); - masm.bind(&join); } FloatRegister output = ToFloatRegister(ins->output()); masm.loadAlignedFloat32x4(Address(StackPointer, 0), output); + Label join; + masm.jump(&join); + + { + masm.bind(&bail); + masm.setFramePushed(masm.framePushed() + Simd128DataSize * 2); + masm.freeStack(Simd128DataSize * 2); + bailout(ins->snapshot()); + } + + masm.bind(&join); masm.freeStack(Simd128DataSize * 2); }