commit c86d5fd6f9060cce9fecd654fcd951d8188c36e4
parent 677f59ac097c07fd9466cd8b4df0dcef45faaf39
Author: André Bargull <andre.bargull@gmail.com>
Date: Fri, 17 Oct 2025 11:25:44 +0000
Bug 1994189: Emit fewer instructions for floating point comparison. r=spidermonkey-reviewers,iain
`x !== x` produced this assembly:
```asm
[Codegen] # LIR=CompareD
[Codegen] a20022d3 feq.d t0, ft0, ft0
[Codegen] a2002ed3 feq.d t4, ft0, ft0
[Codegen] 01d2f2b3 and t0, t0, t4
[Codegen] 0012c293 xori t0, t0, 0x1
[Codegen] .use Llabel 7ffcb6bc81b0 on 100
[Codegen] 00029063 bne t0, zero, 0 -> 0x7ffcb6bc7f3c
[Codegen] a20022d3 feq.d t0, ft0, ft0
[Codegen] .set Llabel 7ffcb6bc81b0 108
[Codegen] 0012c293 xori t0, t0, 0x1
[Codegen] a2002ed3 feq.d t4, ft0, ft0
[Codegen] a2002f53 feq.d t5, ft0, ft0
[Codegen] 01eefeb3 and t4, t4, t5
[Codegen] 001ece93 xori t4, t4, 0x1
[Codegen] 01d2e2b3 or t0, t0, t4
```
And now it's just:
```asm
[Codegen] # LIR=CompareD
[Codegen] a20022d3 feq.d t0, ft0, ft0
[Codegen] 0012c293 xori t0, t0, 0x1
```
Differential Revision: https://phabricator.services.mozilla.com/D268545
Diffstat:
2 files changed, 92 insertions(+), 60 deletions(-)
diff --git a/js/src/jit/riscv64/Assembler-riscv64.h b/js/src/jit/riscv64/Assembler-riscv64.h
@@ -354,8 +354,6 @@ class Assembler : public AssemblerShared,
DoubleGreaterThanOrEqualOrUnordered,
DoubleLessThanOrUnordered,
DoubleLessThanOrEqualOrUnordered,
- FIRST_UNORDERED = DoubleUnordered,
- LAST_UNORDERED = DoubleLessThanOrEqualOrUnordered
};
Register getStackPointer() const { return StackPointer; }
diff --git a/js/src/jit/riscv64/MacroAssembler-riscv64.cpp b/js/src/jit/riscv64/MacroAssembler-riscv64.cpp
@@ -365,36 +365,58 @@ void MacroAssemblerRiscv64::ma_compareF32(Register rd, DoubleCondition cc,
FloatRegister cmp1,
FloatRegister cmp2) {
switch (cc) {
- case DoubleEqualOrUnordered:
case DoubleEqual:
feq_s(rd, cmp1, cmp2);
- break;
- case DoubleNotEqualOrUnordered:
+ return;
+ case DoubleEqualOrUnordered: {
+ UseScratchRegisterScope temps(this);
+ Register scratch = temps.Acquire();
+ flt_s(rd, cmp1, cmp2);
+ flt_s(scratch, cmp2, cmp1);
+ or_(rd, rd, scratch);
+ NegateBool(rd, rd);
+ return;
+ }
case DoubleNotEqual: {
- Label done;
- CompareIsNanF32(rd, cmp1, cmp2);
- ma_branch(&done, Equal, rd, Operand(1));
+ UseScratchRegisterScope temps(this);
+ Register scratch = temps.Acquire();
+ flt_s(rd, cmp1, cmp2);
+ flt_s(scratch, cmp2, cmp1);
+ or_(rd, rd, scratch);
+ return;
+ }
+ case DoubleNotEqualOrUnordered:
feq_s(rd, cmp1, cmp2);
- bind(&done);
NegateBool(rd, rd);
- break;
- }
- case DoubleLessThanOrUnordered:
+ return;
case DoubleLessThan:
flt_s(rd, cmp1, cmp2);
- break;
- case DoubleGreaterThanOrEqualOrUnordered:
+ return;
+ case DoubleLessThanOrUnordered:
+ fle_s(rd, cmp2, cmp1);
+ NegateBool(rd, rd);
+ return;
case DoubleGreaterThanOrEqual:
fle_s(rd, cmp2, cmp1);
- break;
- case DoubleLessThanOrEqualOrUnordered:
+ return;
+ case DoubleGreaterThanOrEqualOrUnordered:
+ flt_s(rd, cmp1, cmp2);
+ NegateBool(rd, rd);
+ return;
case DoubleLessThanOrEqual:
fle_s(rd, cmp1, cmp2);
- break;
- case DoubleGreaterThanOrUnordered:
+ return;
+ case DoubleLessThanOrEqualOrUnordered:
+ flt_s(rd, cmp2, cmp1);
+ NegateBool(rd, rd);
+ return;
case DoubleGreaterThan:
flt_s(rd, cmp2, cmp1);
- break;
+ return;
+ case DoubleGreaterThanOrUnordered:
+ fle_s(rd, cmp1, cmp2);
+ NegateBool(rd, rd);
+ return;
case DoubleOrdered:
CompareIsNotNanF32(rd, cmp1, cmp2);
return;
@@ -402,47 +424,64 @@ void MacroAssemblerRiscv64::ma_compareF32(Register rd, DoubleCondition cc,
CompareIsNanF32(rd, cmp1, cmp2);
return;
}
- if (cc >= FIRST_UNORDERED && cc <= LAST_UNORDERED) {
- UseScratchRegisterScope temps(this);
- Register scratch = temps.Acquire();
- CompareIsNanF32(scratch, cmp1, cmp2);
- or_(rd, rd, scratch);
- }
}
void MacroAssemblerRiscv64::ma_compareF64(Register rd, DoubleCondition cc,
FloatRegister cmp1,
FloatRegister cmp2) {
switch (cc) {
- case DoubleEqualOrUnordered:
case DoubleEqual:
feq_d(rd, cmp1, cmp2);
- break;
- case DoubleNotEqualOrUnordered:
+ return;
+ case DoubleEqualOrUnordered: {
+ UseScratchRegisterScope temps(this);
+ Register scratch = temps.Acquire();
+ flt_d(rd, cmp1, cmp2);
+ flt_d(scratch, cmp2, cmp1);
+ or_(rd, rd, scratch);
+ NegateBool(rd, rd);
+ return;
+ }
case DoubleNotEqual: {
- Label done;
- CompareIsNanF64(rd, cmp1, cmp2);
- ma_branch(&done, Equal, rd, Operand(1));
+ UseScratchRegisterScope temps(this);
+ Register scratch = temps.Acquire();
+ flt_d(rd, cmp1, cmp2);
+ flt_d(scratch, cmp2, cmp1);
+ or_(rd, rd, scratch);
+ return;
+ }
+ case DoubleNotEqualOrUnordered:
feq_d(rd, cmp1, cmp2);
- bind(&done);
NegateBool(rd, rd);
- } break;
- case DoubleLessThanOrUnordered:
+ return;
case DoubleLessThan:
flt_d(rd, cmp1, cmp2);
- break;
- case DoubleGreaterThanOrEqualOrUnordered:
+ return;
+ case DoubleLessThanOrUnordered:
+ fle_d(rd, cmp2, cmp1);
+ NegateBool(rd, rd);
+ return;
case DoubleGreaterThanOrEqual:
fle_d(rd, cmp2, cmp1);
- break;
- case DoubleLessThanOrEqualOrUnordered:
+ return;
+ case DoubleGreaterThanOrEqualOrUnordered:
+ flt_d(rd, cmp1, cmp2);
+ NegateBool(rd, rd);
+ return;
case DoubleLessThanOrEqual:
fle_d(rd, cmp1, cmp2);
- break;
- case DoubleGreaterThanOrUnordered:
+ return;
+ case DoubleLessThanOrEqualOrUnordered:
+ flt_d(rd, cmp2, cmp1);
+ NegateBool(rd, rd);
+ return;
case DoubleGreaterThan:
flt_d(rd, cmp2, cmp1);
- break;
+ return;
+ case DoubleGreaterThanOrUnordered:
+ fle_d(rd, cmp1, cmp2);
+ NegateBool(rd, rd);
+ return;
case DoubleOrdered:
CompareIsNotNanF64(rd, cmp1, cmp2);
return;
@@ -450,13 +489,6 @@ void MacroAssemblerRiscv64::ma_compareF64(Register rd, DoubleCondition cc,
CompareIsNanF64(rd, cmp1, cmp2);
return;
}
-
- if (cc >= FIRST_UNORDERED && cc <= LAST_UNORDERED) {
- UseScratchRegisterScope temps(this);
- Register scratch = temps.Acquire();
- CompareIsNanF64(scratch, cmp1, cmp2);
- or_(rd, rd, scratch);
- }
}
void MacroAssemblerRiscv64Compat::movePtr(Register src, Register dest) {
@@ -6201,24 +6233,26 @@ void MacroAssemblerRiscv64::ma_call(ImmPtr dest) {
void MacroAssemblerRiscv64::CompareIsNotNanF32(Register rd, FPURegister cmp1,
FPURegister cmp2) {
- UseScratchRegisterScope temps(this);
- BlockTrampolinePoolScope block_trampoline_pool(this, 3);
- Register scratch = temps.Acquire();
+ feq_s(rd, cmp1, cmp1); // rd <- !isNan(cmp1)
+ if (cmp1 != cmp2) {
+ UseScratchRegisterScope temps(this);
+ Register scratch = temps.Acquire();
- feq_s(rd, cmp1, cmp1); // rd <- !isNan(cmp1)
- feq_s(scratch, cmp2, cmp2); // scratch <- !isNaN(cmp2)
- ma_and(rd, rd, scratch); // rd <- !isNan(cmp1) && !isNan(cmp2)
+ feq_s(scratch, cmp2, cmp2); // scratch <- !isNaN(cmp2)
+ ma_and(rd, rd, scratch); // rd <- !isNan(cmp1) && !isNan(cmp2)
+ }
}
void MacroAssemblerRiscv64::CompareIsNotNanF64(Register rd, FPURegister cmp1,
FPURegister cmp2) {
- UseScratchRegisterScope temps(this);
- BlockTrampolinePoolScope block_trampoline_pool(this, 3);
- Register scratch = temps.Acquire();
+ feq_d(rd, cmp1, cmp1); // rd <- !isNan(cmp1)
+ if (cmp1 != cmp2) {
+ UseScratchRegisterScope temps(this);
+ Register scratch = temps.Acquire();
- feq_d(rd, cmp1, cmp1); // rd <- !isNan(cmp1)
- feq_d(scratch, cmp2, cmp2); // scratch <- !isNaN(cmp2)
- ma_and(rd, rd, scratch); // rd <- !isNan(cmp1) && !isNan(cmp2)
+ feq_d(scratch, cmp2, cmp2); // scratch <- !isNaN(cmp2)
+ ma_and(rd, rd, scratch); // rd <- !isNan(cmp1) && !isNan(cmp2)
+ }
}
void MacroAssemblerRiscv64::CompareIsNanF32(Register rd, FPURegister cmp1,