зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1752504: Fold binary MIR operations involving NaN. r=jandem
Differential Revision: https://phabricator.services.mozilla.com/D218747
This commit is contained in:
Родитель
25ca34e36c
Коммит
c29d5c26c2
|
@ -1992,7 +1992,7 @@ function rint32tobigint(i) {
|
|||
let uceFault_nantozero_nan = eval(`(${uceFault})`.replace('uceFault', 'uceFault_nantozero_nan'));
|
||||
function rnantozero_nan(i) {
|
||||
// Note: |x| must be Double-typed.
|
||||
var x = (i + 0.5) * NaN;
|
||||
var x = NaN ** (i + 0.5);
|
||||
var y = x ? x : +0;
|
||||
if (uceFault_nantozero_nan(i) || uceFault_nantozero_nan(i))
|
||||
assertEq(y, +0);
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
const values = [
|
||||
-Infinity,
|
||||
-Number.MAX_VALUE,
|
||||
-Number.MIN_VALUE,
|
||||
-0,
|
||||
|
||||
+0,
|
||||
+Number.MIN_VALUE,
|
||||
+Number.MAX_VALUE
|
||||
+Infinity,
|
||||
|
||||
-123,
|
||||
-0.5,
|
||||
+123,
|
||||
+0.5,
|
||||
];
|
||||
|
||||
for (let i = 0; i < 200; ++i) {
|
||||
let val = values[i % values.length];
|
||||
|
||||
// rhs is NaN
|
||||
assertEq(val + NaN, NaN);
|
||||
assertEq(val - NaN, NaN);
|
||||
assertEq(val * NaN, NaN);
|
||||
assertEq(val / NaN, NaN);
|
||||
assertEq(val % NaN, NaN);
|
||||
assertEq(val ** NaN, NaN);
|
||||
|
||||
// rhs is undefined, ToNumber(undefined) is NaN
|
||||
assertEq(val + undefined, NaN);
|
||||
assertEq(val - undefined, NaN);
|
||||
assertEq(val * undefined, NaN);
|
||||
assertEq(val / undefined, NaN);
|
||||
assertEq(val % undefined, NaN);
|
||||
assertEq(val ** undefined, NaN);
|
||||
|
||||
// lhs is NaN
|
||||
assertEq(NaN + val, NaN);
|
||||
assertEq(NaN - val, NaN);
|
||||
assertEq(NaN * val, NaN);
|
||||
assertEq(NaN / val, NaN);
|
||||
assertEq(NaN % val, NaN);
|
||||
assertEq(NaN ** val, (val === 0 ? 1 : NaN));
|
||||
|
||||
// lhs is undefined, ToNumber(undefined) is NaN
|
||||
assertEq(undefined + val, NaN);
|
||||
assertEq(undefined - val, NaN);
|
||||
assertEq(undefined * val, NaN);
|
||||
assertEq(undefined / val, NaN);
|
||||
assertEq(undefined % val, NaN);
|
||||
assertEq(undefined ** val, (val === 0 ? 1 : NaN));
|
||||
}
|
|
@ -309,6 +309,40 @@ static MConstant* EvaluateConstantOperands(TempAllocator& alloc,
|
|||
return MConstant::New(alloc, retVal);
|
||||
}
|
||||
|
||||
static MConstant* EvaluateConstantNaNOperand(MBinaryInstruction* ins) {
|
||||
auto* left = ins->lhs();
|
||||
auto* right = ins->rhs();
|
||||
|
||||
MOZ_ASSERT(IsTypeRepresentableAsDouble(left->type()));
|
||||
MOZ_ASSERT(IsTypeRepresentableAsDouble(right->type()));
|
||||
MOZ_ASSERT(left->type() == ins->type());
|
||||
MOZ_ASSERT(right->type() == ins->type());
|
||||
|
||||
// Don't fold NaN if we can't return a floating point type.
|
||||
if (!IsFloatingPointType(ins->type())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!left->isConstant() || !right->isConstant(),
|
||||
"EvaluateConstantOperands should have handled this case");
|
||||
|
||||
// One operand must be a constant NaN.
|
||||
MConstant* cst;
|
||||
if (left->isConstant()) {
|
||||
cst = left->toConstant();
|
||||
} else if (right->isConstant()) {
|
||||
cst = right->toConstant();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
if (!std::isnan(cst->numberToDouble())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Fold to constant NaN.
|
||||
return cst;
|
||||
}
|
||||
|
||||
static MMul* EvaluateExactReciprocal(TempAllocator& alloc, MDiv* ins) {
|
||||
// we should fold only when it is a floating point operation
|
||||
if (!IsFloatingPointType(ins->type())) {
|
||||
|
@ -2844,6 +2878,11 @@ MDefinition* MBinaryArithInstruction::foldsTo(TempAllocator& alloc) {
|
|||
return folded;
|
||||
}
|
||||
|
||||
if (MConstant* folded = EvaluateConstantNaNOperand(this)) {
|
||||
MOZ_ASSERT(!isTruncated());
|
||||
return folded;
|
||||
}
|
||||
|
||||
if (mustPreserveNaN_) {
|
||||
return this;
|
||||
}
|
||||
|
@ -3224,6 +3263,11 @@ MDefinition* MPow::foldsConstantPower(TempAllocator& alloc) {
|
|||
return multiply(y, y);
|
||||
}
|
||||
|
||||
// Math.pow(x, NaN) == NaN.
|
||||
if (std::isnan(pow)) {
|
||||
return power();
|
||||
}
|
||||
|
||||
// No optimization
|
||||
return nullptr;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче