diff --git a/js/src/wasm/WasmBaselineCompile.cpp b/js/src/wasm/WasmBaselineCompile.cpp index c3fdb98197..e58fffdf71 100644 --- a/js/src/wasm/WasmBaselineCompile.cpp +++ b/js/src/wasm/WasmBaselineCompile.cpp @@ -1709,6 +1709,22 @@ class BaseCompiler return true; } + [[nodiscard]] bool peekConstI32(int32_t* c) { + Stk& v = stk_.back(); + if (v.kind() != Stk::ConstI32) + return false; + *c = v.i32val(); + return true; + } + + [[nodiscard]] bool peekConstI64(int64_t* c) { + Stk& v = stk_.back(); + if (v.kind() != Stk::ConstI64) + return false; + *c = v.i64val(); + return true; + } + [[nodiscard]] bool popConstPositivePowerOfTwoI32(int32_t& c, uint_fast8_t& power, int32_t cutoff) @@ -2652,12 +2668,15 @@ class BaseCompiler } #ifndef INT_DIV_I64_CALLOUT - void quotientI64(RegI64 rhs, RegI64 srcDest, IsUnsigned isUnsigned) { + void quotientI64(RegI64 rhs, RegI64 srcDest, IsUnsigned isUnsigned, + bool isConst, int64_t c) + { Label done; - checkDivideByZeroI64(rhs); + if (!isConst || c == 0) + checkDivideByZeroI64(rhs); - if (!isUnsigned) + if (!isUnsigned && (!isConst || c == -1)) checkDivideSignedOverflowI64(rhs, srcDest, &done, ZeroOnOverflow(false)); # if defined(JS_CODEGEN_X64) @@ -2682,12 +2701,15 @@ class BaseCompiler masm.bind(&done); } - void remainderI64(RegI64 rhs, RegI64 srcDest, IsUnsigned isUnsigned) { + void remainderI64(RegI64 rhs, RegI64 srcDest, IsUnsigned isUnsigned, + bool isConst, int64_t c) + { Label done; - checkDivideByZeroI64(rhs); + if (!isConst || c == 0) + checkDivideByZeroI64(rhs); - if (!isUnsigned) + if (!isUnsigned && (!isConst || c == -1)) checkDivideSignedOverflowI64(rhs, srcDest, &done, ZeroOnOverflow(true)); # if defined(JS_CODEGEN_X64) @@ -4468,12 +4490,15 @@ BaseCompiler::emitQuotientI32() pushI32(r); } } else { + bool isConst = peekConstI32(&c); RegI32 r0, r1; pop2xI32ForIntMulDiv(&r0, &r1); Label done; - checkDivideByZeroI32(r1, r0, &done); - checkDivideSignedOverflowI32(r1, r0, &done, ZeroOnOverflow(false)); + if (!isConst || c == 0) + checkDivideByZeroI32(r1, r0, &done); + if (!isConst || c == -1) + checkDivideSignedOverflowI32(r1, r0, &done, ZeroOnOverflow(false)); masm.quotient32(r1, r0, IsUnsigned(false)); masm.bind(&done); @@ -4494,11 +4519,13 @@ BaseCompiler::emitQuotientU32() pushI32(r); } } else { + bool isConst = peekConstI32(&c); RegI32 r0, r1; pop2xI32ForIntMulDiv(&r0, &r1); Label done; - checkDivideByZeroI32(r1, r0, &done); + if (!isConst || c == 0) + checkDivideByZeroI32(r1, r0, &done); masm.quotient32(r1, r0, IsUnsigned(true)); masm.bind(&done); @@ -4529,12 +4556,15 @@ BaseCompiler::emitRemainderI32() pushI32(r); } else { + bool isConst = peekConstI32(&c); RegI32 r0, r1; pop2xI32ForIntMulDiv(&r0, &r1); Label done; - checkDivideByZeroI32(r1, r0, &done); - checkDivideSignedOverflowI32(r1, r0, &done, ZeroOnOverflow(true)); + if (!isConst || c == 0) + checkDivideByZeroI32(r1, r0, &done); + if (!isConst || c == -1) + checkDivideSignedOverflowI32(r1, r0, &done, ZeroOnOverflow(true)); masm.remainder32(r1, r0, IsUnsigned(false)); masm.bind(&done); @@ -4553,11 +4583,13 @@ BaseCompiler::emitRemainderU32() masm.and32(Imm32(c-1), r); pushI32(r); } else { + bool isConst = peekConstI32(&c); RegI32 r0, r1; pop2xI32ForIntMulDiv(&r0, &r1); Label done; - checkDivideByZeroI32(r1, r0, &done); + if (!isConst || c == 0) + checkDivideByZeroI32(r1, r0, &done); masm.remainder32(r1, r0, IsUnsigned(true)); masm.bind(&done); @@ -4586,9 +4618,10 @@ BaseCompiler::emitQuotientI64() pushI64(r); } } else { + bool isConst = peekConstI64(&c); RegI64 r0, r1; pop2xI64ForIntDiv(&r0, &r1); - quotientI64(r1, r0, IsUnsigned(false)); + quotientI64(r1, r0, IsUnsigned(false), isConst, c); freeI64(r1); pushI64(r0); } @@ -4610,9 +4643,10 @@ BaseCompiler::emitQuotientU64() pushI64(r); } } else { + bool isConst = peekConstI64(&c); RegI64 r0, r1; pop2xI64ForIntDiv(&r0, &r1); - quotientI64(r1, r0, IsUnsigned(true)); + quotientI64(r1, r0, IsUnsigned(true), isConst, c); freeI64(r1); pushI64(r0); } @@ -4645,9 +4679,10 @@ BaseCompiler::emitRemainderI64() pushI64(r); } else { + bool isConst = peekConstI64(&c); RegI64 r0, r1; pop2xI64ForIntDiv(&r0, &r1); - remainderI64(r1, r0, IsUnsigned(false)); + remainderI64(r1, r0, IsUnsigned(false), isConst, c); freeI64(r1); pushI64(r0); } @@ -4667,9 +4702,10 @@ BaseCompiler::emitRemainderU64() masm.and64(Imm64(c-1), r); pushI64(r); } else { + bool isConst = peekConstI64(&c); RegI64 r0, r1; pop2xI64ForIntDiv(&r0, &r1); - remainderI64(r1, r0, IsUnsigned(true)); + remainderI64(r1, r0, IsUnsigned(true), isConst, c); freeI64(r1); pushI64(r0); }