1326160 Wasm baseline: Division by nonzero constants can omit divide-by-zero check

1326160 - Omit divide by zero and overflow checks for some constants
This commit is contained in:
win7-7 2025-12-29 01:03:56 +02:00 committed by wuggy
commit 9f9349f296

View file

@ -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);
}