diff --git a/common.gypi b/common.gypi index 9fc77e9445cb..b1bae4999b26 100644 --- a/common.gypi +++ b/common.gypi @@ -44,7 +44,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.15', + 'v8_embedder_string': '-node.16', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/compiler/backend/loong64/code-generator-loong64.cc b/deps/v8/src/compiler/backend/loong64/code-generator-loong64.cc index 9bc155f8218c..83dbab96a70b 100644 --- a/deps/v8/src/compiler/backend/loong64/code-generator-loong64.cc +++ b/deps/v8/src/compiler/backend/loong64/code-generator-loong64.cc @@ -1397,6 +1397,22 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( i.InputOperand(1), scratch); break; } + case kLoong64Add64_3: { + Register low = i.OutputRegister(0); + UseScratchRegisterScope temps(masm()); + Register scratch = temps.Acquire(); + __ Add_d(scratch, i.InputRegister(0), i.InputOperand(1)); + if (instr->OutputCount() > 1) { + Register high = i.OutputRegister(1); + __ Sltu(high, scratch, i.InputRegister(0)); + __ Add_d(low, scratch, i.InputOperand(2)); + __ Sltu(scratch, low, scratch); + __ Add_d(high, high, scratch); + } else { + __ Add_d(low, scratch, i.InputOperand(2)); + } + break; + } case kLoong64Add128: { UseScratchRegisterScope temps(masm()); Register scratch = temps.Acquire(); diff --git a/deps/v8/src/compiler/backend/loong64/instruction-codes-loong64.h b/deps/v8/src/compiler/backend/loong64/instruction-codes-loong64.h index 92396bc25a93..5939b1c59e56 100644 --- a/deps/v8/src/compiler/backend/loong64/instruction-codes-loong64.h +++ b/deps/v8/src/compiler/backend/loong64/instruction-codes-loong64.h @@ -55,6 +55,7 @@ namespace compiler { V(Loong64Add_w) \ V(Loong64AddOvf_d) \ V(Loong64AddOvf_w) \ + V(Loong64Add64_3) \ V(Loong64Add128) \ V(Loong64Sub_d) \ V(Loong64Sub_w) \ diff --git a/deps/v8/src/compiler/backend/loong64/instruction-selector-loong64.cc b/deps/v8/src/compiler/backend/loong64/instruction-selector-loong64.cc index 735b1d90d806..a719e188a64f 100644 --- a/deps/v8/src/compiler/backend/loong64/instruction-selector-loong64.cc +++ b/deps/v8/src/compiler/backend/loong64/instruction-selector-loong64.cc @@ -33,6 +33,13 @@ class Loong64OperandGenerator final : public OperandGenerator { return UseRegister(node); } + InstructionOperand UseUniqueOperand(OpIndex node, InstructionCode opcode) { + if (CanBeImmediate(node, opcode)) { + return UseImmediate(node); + } + return UseUniqueRegister(node); + } + bool IsImmediateZero(OpIndex node) { if (const ConstantOp* constant = selector()->Get(node).TryCast()) { @@ -1537,6 +1544,30 @@ void InstructionSelector::VisitUint64MulHigh(OpIndex node) { VisitRRR(this, kLoong64Mulh_du, node); } +void InstructionSelector::VisitUint64Add3WithCarry(OpIndex node) { + Loong64OperandGenerator g(this); + const auto& op = Get(node).Cast(); + + OptionalV out_low = FindProjection(node, 0); + OptionalV out_high = FindProjection(node, 1); + + InstructionOperand inputs[3]; + size_t input_count = 0; + inputs[input_count++] = g.UseRegister(op.first()); + inputs[input_count++] = g.UseOperand(op.second(), kLoong64Add_d); + inputs[input_count++] = g.UseUniqueOperand(op.third(), kLoong64Add_d); + + InstructionOperand outputs[2]; + size_t output_count = 0; + outputs[output_count++] = + g.DefineAsRegister(out_low.valid() ? out_low.value() : node); + if (out_high.valid() && IsUsed(out_high.value())) { + outputs[output_count++] = g.DefineAsRegister(out_high.value()); + } + + Emit(kLoong64Add64_3, output_count, outputs, input_count, inputs); +} + void InstructionSelector::VisitInt64Mul(OpIndex node) { Loong64OperandGenerator g(this); const WordBinopOp& mul = Get(node).Cast(); diff --git a/deps/v8/src/compiler/backend/mips64/code-generator-mips64.cc b/deps/v8/src/compiler/backend/mips64/code-generator-mips64.cc index 750cceb960d5..2f1edb777c98 100644 --- a/deps/v8/src/compiler/backend/mips64/code-generator-mips64.cc +++ b/deps/v8/src/compiler/backend/mips64/code-generator-mips64.cc @@ -1024,6 +1024,22 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( __ DaddOverflow(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1), kScratchReg); break; + case kMips64Add64_3: { + Register low = i.OutputRegister(0); + UseScratchRegisterScope temps(masm()); + Register scratch = temps.Acquire(); + __ Daddu(scratch, i.InputRegister(0), i.InputOperand(1)); + if (instr->OutputCount() > 1) { + Register high = i.OutputRegister(1); + __ Sltu(high, scratch, i.InputRegister(0)); + __ Daddu(low, scratch, i.InputOperand(2)); + __ Sltu(scratch, low, scratch); + __ Daddu(high, high, scratch); + } else { + __ Daddu(low, scratch, i.InputOperand(2)); + } + break; + } case kMips64Add128: { UseScratchRegisterScope temps(masm()); Register scratch = temps.Acquire(); diff --git a/deps/v8/src/compiler/backend/mips64/instruction-codes-mips64.h b/deps/v8/src/compiler/backend/mips64/instruction-codes-mips64.h index ecfb5b2c3a45..27604bcd75db 100644 --- a/deps/v8/src/compiler/backend/mips64/instruction-codes-mips64.h +++ b/deps/v8/src/compiler/backend/mips64/instruction-codes-mips64.h @@ -16,6 +16,7 @@ namespace compiler { V(Mips64Add) \ V(Mips64Dadd) \ V(Mips64DaddOvf) \ + V(Mips64Add64_3) \ V(Mips64Add128) \ V(Mips64Sub) \ V(Mips64Dsub) \ diff --git a/deps/v8/src/compiler/backend/mips64/instruction-scheduler-mips64.cc b/deps/v8/src/compiler/backend/mips64/instruction-scheduler-mips64.cc index d19373e102a4..24c96e56f29f 100644 --- a/deps/v8/src/compiler/backend/mips64/instruction-scheduler-mips64.cc +++ b/deps/v8/src/compiler/backend/mips64/instruction-scheduler-mips64.cc @@ -66,6 +66,7 @@ int InstructionScheduler::GetTargetInstructionFlags( case kMips64MulHighU: case kMips64Dadd: case kMips64DaddOvf: + case kMips64Add64_3: case kMips64Add128: case kMips64Dclz: case kMips64Dctz: diff --git a/deps/v8/src/compiler/backend/mips64/instruction-selector-mips64.cc b/deps/v8/src/compiler/backend/mips64/instruction-selector-mips64.cc index b23b324c3932..adc54b275601 100644 --- a/deps/v8/src/compiler/backend/mips64/instruction-selector-mips64.cc +++ b/deps/v8/src/compiler/backend/mips64/instruction-selector-mips64.cc @@ -32,6 +32,13 @@ class Mips64OperandGenerator final : public OperandGenerator { return UseRegister(node); } + InstructionOperand UseUniqueOperand(OpIndex node, InstructionCode opcode) { + if (CanBeImmediate(node, opcode)) { + return UseImmediate(node); + } + return UseUniqueRegister(node); + } + // Use the zero register if the node has the immediate value zero, otherwise // assign a register. InstructionOperand UseRegisterOrImmediateZero(OpIndex node) { @@ -763,6 +770,30 @@ void InstructionSelector::VisitUint64MulHigh(OpIndex node) { VisitRRR(this, kMips64DMulHighU, node); } +void InstructionSelector::VisitUint64Add3WithCarry(OpIndex node) { + Mips64OperandGenerator g(this); + const auto& op = Get(node).Cast(); + + OptionalV out_low = FindProjection(node, 0); + OptionalV out_high = FindProjection(node, 1); + + InstructionOperand inputs[3]; + size_t input_count = 0; + inputs[input_count++] = g.UseRegister(op.first()); + inputs[input_count++] = g.UseOperand(op.second(), kMips64Dadd); + inputs[input_count++] = g.UseUniqueOperand(op.third(), kMips64Dadd); + + InstructionOperand outputs[2]; + size_t output_count = 0; + outputs[output_count++] = + g.DefineAsRegister(out_low.valid() ? out_low.value() : node); + if (out_high.valid() && IsUsed(out_high.value())) { + outputs[output_count++] = g.DefineAsRegister(out_high.value()); + } + + Emit(kMips64Add64_3, output_count, outputs, input_count, inputs); +} + void InstructionSelector::VisitInt64Mul(OpIndex node) { // TODO(MIPS_dev): May could be optimized like in Turbofan. VisitBinop(this, node, kMips64Dmul, true, kMips64Dmul); diff --git a/deps/v8/src/compiler/turboshaft/machine-optimization-reducer.h b/deps/v8/src/compiler/turboshaft/machine-optimization-reducer.h index 3e2b973e0784..7170bd5a8341 100644 --- a/deps/v8/src/compiler/turboshaft/machine-optimization-reducer.h +++ b/deps/v8/src/compiler/turboshaft/machine-optimization-reducer.h @@ -1639,7 +1639,7 @@ class MachineOptimizationReducer : public Next { } // TODO(ryandiaz): implement on arm64 -#ifdef V8_TARGET_ARCH_X64 +#if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_LOONG64) if (kind == Word64AddSub128BinopOp::Kind::kAdd) { // add128(add128(x, 0, y, 0), z, 0) -> add3(x, y, z) if (const Word64AddSub128BinopOp* nested = TryMatchAdd3(al, ah, bh)) { @@ -1654,7 +1654,7 @@ class MachineOptimizationReducer : public Next { // TODO(ryandiaz): sub128(sub128(x, 0, y, 0), z, 0) -> sub2(x, y, z) // TODO(ryandiaz): sub128(x, 0, add128(y, 0, z, 0)) -> sub2(x, y, z) } -#endif // V8_TARGET_ARCH_X64 +#endif // defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_LOONG64) return Next::ReduceWord64AddSub128Binop(al, ah, bl, bh, kind); } diff --git a/deps/v8/test/unittests/compiler/loong64/turboshaft-instruction-selector-loong64-unittest.cc b/deps/v8/test/unittests/compiler/loong64/turboshaft-instruction-selector-loong64-unittest.cc index 4fe0f84690ae..916e44858e8e 100644 --- a/deps/v8/test/unittests/compiler/loong64/turboshaft-instruction-selector-loong64-unittest.cc +++ b/deps/v8/test/unittests/compiler/loong64/turboshaft-instruction-selector-loong64-unittest.cc @@ -2172,4 +2172,38 @@ TEST_F(TurboshaftInstructionSelectorTest, Word32EqualWithReadOnlyRoot) { EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); } +TEST_F(TurboshaftInstructionSelectorTest, Word64Add3) { + StreamBuilder m(this, MachineType::Uint64(), MachineType::Uint64(), + MachineType::Uint64(), MachineType::Uint64()); + V p0 = m.Parameter(0); + V p1 = m.Parameter(1); + V p2 = m.Parameter(2); + V res = m.Word64Add3(p0, p1, p2); + OpIndex low = m.Projection(res, 0); + OpIndex high = m.Projection(res, 1); + m.Return(m.Word64Add(low, high)); + Stream s = m.Build(); + ASSERT_EQ(2U, s.size()); + EXPECT_EQ(kLoong64Add64_3, s[0]->arch_opcode()); + EXPECT_EQ(kLoong64Add_d, s[1]->arch_opcode()); + ASSERT_EQ(3U, s[0]->InputCount()); + ASSERT_EQ(2U, s[0]->OutputCount()); +} + +TEST_F(TurboshaftInstructionSelectorTest, Word64Add3UnusedHigh) { + StreamBuilder m(this, MachineType::Uint64(), MachineType::Uint64(), + MachineType::Uint64(), MachineType::Uint64()); + V p0 = m.Parameter(0); + V p1 = m.Parameter(1); + V p2 = m.Parameter(2); + V res = m.Word64Add3(p0, p1, p2); + OpIndex low = m.Projection(res, 0); + m.Return(low); + Stream s = m.Build(); + ASSERT_EQ(1U, s.size()); + EXPECT_EQ(kLoong64Add64_3, s[0]->arch_opcode()); + ASSERT_EQ(3U, s[0]->InputCount()); + ASSERT_EQ(1U, s[0]->OutputCount()); +} + } // namespace v8::internal::compiler::turboshaft diff --git a/deps/v8/test/unittests/compiler/mips64/turboshaft-instruction-selector-mips64-unittest.cc b/deps/v8/test/unittests/compiler/mips64/turboshaft-instruction-selector-mips64-unittest.cc index b16c21d19684..eedb0081a0d0 100644 --- a/deps/v8/test/unittests/compiler/mips64/turboshaft-instruction-selector-mips64-unittest.cc +++ b/deps/v8/test/unittests/compiler/mips64/turboshaft-instruction-selector-mips64-unittest.cc @@ -2112,6 +2112,40 @@ TEST_F(TurboshaftInstructionSelectorTest, AtomicStoreWithWriteBarrier) { RecordWriteMode::kValueIsAny); } +TEST_F(TurboshaftInstructionSelectorTest, Word64Add3) { + StreamBuilder m(this, MachineType::Uint64(), MachineType::Uint64(), + MachineType::Uint64(), MachineType::Uint64()); + V p0 = m.Parameter(0); + V p1 = m.Parameter(1); + V p2 = m.Parameter(2); + V res = m.Word64Add3(p0, p1, p2); + OpIndex low = m.Projection(res, 0); + OpIndex high = m.Projection(res, 1); + m.Return(m.Word64Add(low, high)); + Stream s = m.Build(); + ASSERT_EQ(2U, s.size()); + EXPECT_EQ(kMips64Add64_3, s[0]->arch_opcode()); + EXPECT_EQ(kMips64Dadd, s[1]->arch_opcode()); + ASSERT_EQ(3U, s[0]->InputCount()); + ASSERT_EQ(2U, s[0]->OutputCount()); +} + +TEST_F(TurboshaftInstructionSelectorTest, Word64Add3UnusedHigh) { + StreamBuilder m(this, MachineType::Uint64(), MachineType::Uint64(), + MachineType::Uint64(), MachineType::Uint64()); + V p0 = m.Parameter(0); + V p1 = m.Parameter(1); + V p2 = m.Parameter(2); + V res = m.Word64Add3(p0, p1, p2); + OpIndex low = m.Projection(res, 0); + m.Return(low); + Stream s = m.Build(); + ASSERT_EQ(1U, s.size()); + EXPECT_EQ(kMips64Add64_3, s[0]->arch_opcode()); + ASSERT_EQ(3U, s[0]->InputCount()); + ASSERT_EQ(1U, s[0]->OutputCount()); +} + } // namespace turboshaft } // namespace compiler } // namespace internal