[riscv] Separate single and double precision zero to different registers to avoid misuse.
R=yahan@iscas.ac.cn Bug: v8:13191 Change-Id: I8c7ccb90c4e8a5b8ca5d88fc11c99fbe876621bc Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3831142 Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Reviewed-by: Yahan Lu <yahan@iscas.ac.cn> Commit-Queue: Yahan Lu <yahan@iscas.ac.cn> Cr-Commit-Position: refs/heads/main@{#82889}
This commit is contained in:
parent
9526c2936d
commit
dad963c84f
1
AUTHORS
1
AUTHORS
@ -42,6 +42,7 @@ Cloudflare, Inc. <*@cloudflare.com>
|
||||
Julia Computing, Inc. <*@juliacomputing.com>
|
||||
CodeWeavers, Inc. <*@codeweavers.com>
|
||||
Alibaba, Inc. <*@alibaba-inc.com>
|
||||
SiFive, Inc. <*@sifive.com>
|
||||
|
||||
Aaron Bieber <deftly@gmail.com>
|
||||
Aaron O'Mullan <aaron.omullan@gmail.com>
|
||||
|
@ -558,6 +558,7 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
|
||||
__ MultiPushFPU(kCalleeSavedFPU);
|
||||
// Set up the reserved register for 0.0.
|
||||
__ LoadFPRImmediate(kDoubleRegZero, 0.0);
|
||||
__ LoadFPRImmediate(kSingleRegZero, 0.0f);
|
||||
|
||||
// Initialize the root register.
|
||||
// C calling convention. The first argument is passed in a0.
|
||||
|
@ -3360,16 +3360,15 @@ void TurboAssembler::LoadFPRImmediate(FPURegister dst, uint32_t src) {
|
||||
ASM_CODE_COMMENT(this);
|
||||
// Handle special values first.
|
||||
if (src == base::bit_cast<uint32_t>(0.0f) && has_single_zero_reg_set_) {
|
||||
if (dst != kDoubleRegZero) fmv_s(dst, kDoubleRegZero);
|
||||
if (dst != kSingleRegZero) fmv_s(dst, kSingleRegZero);
|
||||
} else if (src == base::bit_cast<uint32_t>(-0.0f) &&
|
||||
has_single_zero_reg_set_) {
|
||||
Neg_s(dst, kDoubleRegZero);
|
||||
Neg_s(dst, kSingleRegZero);
|
||||
} else {
|
||||
if (dst == kDoubleRegZero) {
|
||||
if (dst == kSingleRegZero) {
|
||||
DCHECK(src == base::bit_cast<uint32_t>(0.0f));
|
||||
fcvt_s_w(dst, zero_reg);
|
||||
has_single_zero_reg_set_ = true;
|
||||
has_double_zero_reg_set_ = false;
|
||||
} else {
|
||||
if (src == base::bit_cast<uint32_t>(0.0f)) {
|
||||
fcvt_s_w(dst, zero_reg);
|
||||
@ -3397,7 +3396,6 @@ void TurboAssembler::LoadFPRImmediate(FPURegister dst, uint64_t src) {
|
||||
DCHECK(src == base::bit_cast<uint64_t>(0.0));
|
||||
fcvt_d_l(dst, zero_reg);
|
||||
has_double_zero_reg_set_ = true;
|
||||
has_single_zero_reg_set_ = false;
|
||||
} else {
|
||||
UseScratchRegisterScope temps(this);
|
||||
Register scratch = temps.Acquire();
|
||||
@ -3413,7 +3411,6 @@ void TurboAssembler::LoadFPRImmediate(FPURegister dst, uint64_t src) {
|
||||
DCHECK(src == base::bit_cast<uint64_t>(0.0));
|
||||
fcvt_d_w(dst, zero_reg);
|
||||
has_double_zero_reg_set_ = true;
|
||||
has_single_zero_reg_set_ = false;
|
||||
} else {
|
||||
// Todo: need to clear the stack content?
|
||||
if (src == base::bit_cast<uint64_t>(0.0)) {
|
||||
@ -4683,12 +4680,10 @@ void TurboAssembler::FPUCanonicalizeNaN(const DoubleRegister dst,
|
||||
// Subtracting 0.0 preserves all inputs except for signalling NaNs, which
|
||||
// become quiet NaNs. We use fsub rather than fadd because fsub preserves -0.0
|
||||
// inputs: -0.0 + 0.0 = 0.0, but -0.0 - 0.0 = -0.0.
|
||||
if (IsDoubleZeroRegSet()) {
|
||||
fsub_d(dst, src, kDoubleRegZero);
|
||||
} else {
|
||||
if (!IsDoubleZeroRegSet()) {
|
||||
LoadFPRImmediate(kDoubleRegZero, 0.0);
|
||||
fsub_d(dst, src, kDoubleRegZero);
|
||||
}
|
||||
fsub_d(dst, src, kDoubleRegZero);
|
||||
}
|
||||
|
||||
void TurboAssembler::MovFromFloatResult(const DoubleRegister dst) {
|
||||
|
@ -263,6 +263,7 @@ constexpr Register kScratchReg2 = s4;
|
||||
constexpr DoubleRegister kScratchDoubleReg = ft0;
|
||||
|
||||
constexpr DoubleRegister kDoubleRegZero = fs9;
|
||||
constexpr DoubleRegister kSingleRegZero = fs10;
|
||||
|
||||
// Define {RegisterName} methods for the register types.
|
||||
DEFINE_REGISTER_NAMES(Register, GENERAL_REGISTERS)
|
||||
|
@ -79,7 +79,7 @@ class RiscvOperandConverter final : public InstructionOperandConverter {
|
||||
}
|
||||
|
||||
DoubleRegister InputOrZeroSingleRegister(size_t index) {
|
||||
if (instr_->InputAt(index)->IsImmediate()) return kDoubleRegZero;
|
||||
if (instr_->InputAt(index)->IsImmediate()) return kSingleRegZero;
|
||||
|
||||
return InputSingleRegister(index);
|
||||
}
|
||||
@ -1260,9 +1260,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
FPUCondition cc =
|
||||
FlagsConditionToConditionCmpFPU(&predicate, instr->flags_condition());
|
||||
|
||||
if ((left == kDoubleRegZero || right == kDoubleRegZero) &&
|
||||
if ((left == kSingleRegZero || right == kSingleRegZero) &&
|
||||
!__ IsSingleZeroRegSet()) {
|
||||
__ LoadFPRImmediate(kDoubleRegZero, 0.0f);
|
||||
__ LoadFPRImmediate(kSingleRegZero, 0.0f);
|
||||
}
|
||||
// compare result set to kScratchReg
|
||||
__ CompareF32(kScratchReg, cc, left, right);
|
||||
@ -1777,8 +1777,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
size_t index = 0;
|
||||
MemOperand operand = i.MemoryOperand(&index);
|
||||
FPURegister ft = i.InputOrZeroSingleRegister(index);
|
||||
if (ft == kDoubleRegZero && !__ IsSingleZeroRegSet()) {
|
||||
__ LoadFPRImmediate(kDoubleRegZero, 0.0f);
|
||||
if (ft == kSingleRegZero && !__ IsSingleZeroRegSet()) {
|
||||
__ LoadFPRImmediate(kSingleRegZero, 0.0f);
|
||||
}
|
||||
__ StoreFloat(ft, operand);
|
||||
break;
|
||||
@ -1787,8 +1787,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
size_t index = 0;
|
||||
MemOperand operand = i.MemoryOperand(&index);
|
||||
FPURegister ft = i.InputOrZeroSingleRegister(index);
|
||||
if (ft == kDoubleRegZero && !__ IsSingleZeroRegSet()) {
|
||||
__ LoadFPRImmediate(kDoubleRegZero, 0.0f);
|
||||
if (ft == kSingleRegZero && !__ IsSingleZeroRegSet()) {
|
||||
__ LoadFPRImmediate(kSingleRegZero, 0.0f);
|
||||
}
|
||||
__ UStoreFloat(ft, operand, kScratchReg);
|
||||
break;
|
||||
@ -4059,16 +4059,20 @@ void CodeGenerator::AssembleArchBoolean(Instruction* instr,
|
||||
return;
|
||||
} else if (instr->arch_opcode() == kRiscvCmpD ||
|
||||
instr->arch_opcode() == kRiscvCmpS) {
|
||||
FPURegister left = i.InputOrZeroDoubleRegister(0);
|
||||
FPURegister right = i.InputOrZeroDoubleRegister(1);
|
||||
if ((instr->arch_opcode() == kRiscvCmpD) &&
|
||||
(left == kDoubleRegZero || right == kDoubleRegZero) &&
|
||||
!__ IsDoubleZeroRegSet()) {
|
||||
__ LoadFPRImmediate(kDoubleRegZero, 0.0);
|
||||
} else if ((instr->arch_opcode() == kRiscvCmpS) &&
|
||||
(left == kDoubleRegZero || right == kDoubleRegZero) &&
|
||||
!__ IsSingleZeroRegSet()) {
|
||||
__ LoadFPRImmediate(kDoubleRegZero, 0.0f);
|
||||
if (instr->arch_opcode() == kRiscvCmpD) {
|
||||
FPURegister left = i.InputOrZeroDoubleRegister(0);
|
||||
FPURegister right = i.InputOrZeroDoubleRegister(1);
|
||||
if ((left == kDoubleRegZero || right == kDoubleRegZero) &&
|
||||
!__ IsDoubleZeroRegSet()) {
|
||||
__ LoadFPRImmediate(kDoubleRegZero, 0.0);
|
||||
}
|
||||
} else {
|
||||
FPURegister left = i.InputOrZeroSingleRegister(0);
|
||||
FPURegister right = i.InputOrZeroSingleRegister(1);
|
||||
if ((left == kSingleRegZero || right == kSingleRegZero) &&
|
||||
!__ IsSingleZeroRegSet()) {
|
||||
__ LoadFPRImmediate(kSingleRegZero, 0.0f);
|
||||
}
|
||||
}
|
||||
bool predicate;
|
||||
FlagsConditionToConditionCmpFPU(&predicate, condition);
|
||||
|
23
test/mjsunit/canonicalize-nan.js
Normal file
23
test/mjsunit/canonicalize-nan.js
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
|
||||
var buf = new Float32Array(1);
|
||||
|
||||
function fill() {
|
||||
buf[0] = 0;
|
||||
};
|
||||
|
||||
// Have single precision zero set.
|
||||
%PrepareFunctionForOptimization(fill);
|
||||
fill();
|
||||
%OptimizeFunctionOnNextCall(fill);
|
||||
fill();
|
||||
|
||||
var array = Array(2).fill(0);
|
||||
|
||||
assertEquals(0, array[1])
|
||||
array[1] = 0.5;
|
||||
assertEquals(0.5, array[1]);
|
Loading…
Reference in New Issue
Block a user