[maglev][arm64] Implement first Float64 operations

Bug: v8:7700
Change-Id: Ib2d9d0cab90042e2b425f56da8022b25b94c4805
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4082208
Commit-Queue: Darius Mercadier <dmercadier@chromium.org>
Reviewed-by: Victor Gomes <victorgomes@chromium.org>
Cr-Commit-Position: refs/heads/main@{#84735}
This commit is contained in:
Darius M 2022-12-08 15:45:58 +01:00 committed by V8 LUCI CQ
parent 73801dac2f
commit ada6f41e91
6 changed files with 196 additions and 38 deletions

View File

@ -1106,16 +1106,18 @@ void TurboAssembler::SmiUntag(Register dst, const MemOperand& src) {
void TurboAssembler::SmiUntag(Register smi) { SmiUntag(smi, smi); }
void TurboAssembler::SmiToInt32(Register smi) {
DCHECK(smi.Is64Bits());
void TurboAssembler::SmiToInt32(Register smi) { SmiToInt32(smi, smi); }
void TurboAssembler::SmiToInt32(Register dst, Register smi) {
DCHECK(dst.Is64Bits());
if (v8_flags.enable_slow_asserts) {
AssertSmi(smi);
}
DCHECK(SmiValuesAre32Bits() || SmiValuesAre31Bits());
if (COMPRESS_POINTERS_BOOL) {
Asr(smi.W(), smi.W(), kSmiShift);
Asr(dst.W(), smi.W(), kSmiShift);
} else {
Lsr(smi, smi, kSmiShift);
Lsr(dst, smi, kSmiShift);
}
}

View File

@ -561,6 +561,7 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
inline void SmiTag(Register smi);
inline void SmiToInt32(Register smi);
inline void SmiToInt32(Register dst, Register smi);
// Calls Abort(msg) if the condition cond is not satisfied.
// Use --debug_code to enable.
@ -1821,7 +1822,7 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
DCHECK(!registers.has(fp_zero));
registers.set(fp_zero);
}
PushQRegList(registers);
PushDRegList(registers);
}
inline void PopAll(DoubleRegList registers,
int stack_slot_size = kDoubleSize) {
@ -1829,7 +1830,7 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
DCHECK(!registers.has(fp_zero));
registers.set(fp_zero);
}
PopQRegList(registers);
PopDRegList(registers);
}
// Push the specified register 'count' times.

View File

@ -100,19 +100,16 @@ inline void MaglevAssembler::Move(MemOperand dst, Register src) {
Str(src, dst);
}
inline void MaglevAssembler::Move(MemOperand dst, DoubleRegister src) {
// TODO(v8:7700): Implement!
UNREACHABLE();
Str(src, dst);
}
inline void MaglevAssembler::Move(Register dst, MemOperand src) {
Ldr(dst, src);
}
inline void MaglevAssembler::Move(DoubleRegister dst, MemOperand src) {
// TODO(v8:7700): Implement!
UNREACHABLE();
Ldr(dst, src);
}
inline void MaglevAssembler::Move(DoubleRegister dst, DoubleRegister src) {
// TODO(v8:7700): Implement!
UNREACHABLE();
fmov(dst, src);
}
inline void MaglevAssembler::Move(Register dst, Smi src) {
MacroAssembler::Move(dst, src);
@ -127,8 +124,7 @@ inline void MaglevAssembler::Move(Register dst, int32_t i) {
Mov(dst, Immediate(i));
}
inline void MaglevAssembler::Move(DoubleRegister dst, double n) {
// TODO(v8:7700): Implement!
UNREACHABLE();
Fmov(dst, n);
}
inline void MaglevAssembler::Move(Register dst, Handle<HeapObject> obj) {
Mov(dst, Operand(obj));

View File

@ -79,6 +79,23 @@ void MaglevAssembler::Allocate(RegisterSnapshot& register_snapshot,
bind(*done);
}
void MaglevAssembler::AllocateHeapNumber(RegisterSnapshot register_snapshot,
Register result,
DoubleRegister value) {
// In the case we need to call the runtime, we should spill the value
// register. Even if it is not live in the next node, otherwise the
// allocation call might trash it.
register_snapshot.live_double_registers.set(value);
Allocate(register_snapshot, result, HeapNumber::kSize);
// `Allocate` needs 2 scratch registers, so it's important to `AcquireX` after
// `Allocate` is done and not before.
UseScratchRegisterScope temps(this);
Register scratch = temps.AcquireX();
LoadRoot(scratch, RootIndex::kHeapNumberMap);
StoreTaggedField(scratch, FieldMemOperand(result, HeapObject::kMapOffset));
Str(value, FieldMemOperand(result, HeapNumber::kValueOffset));
}
void MaglevAssembler::Prologue(Graph* graph) {
if (v8_flags.maglev_ool_prologue) {
// TODO(v8:7700): Implement!

View File

@ -115,13 +115,6 @@ void Int32DecrementWithOverflow::GenerateCode(MaglevAssembler* masm,
__ EmitEagerDeoptIf(vs, DeoptimizeReason::kOverflow, this);
}
UNIMPLEMENTED_NODE(Float64Add)
UNIMPLEMENTED_NODE(Float64Subtract)
UNIMPLEMENTED_NODE(Float64Multiply)
UNIMPLEMENTED_NODE(Float64Divide)
UNIMPLEMENTED_NODE_WITH_CALL(Float64Exponentiate)
UNIMPLEMENTED_NODE(Float64Modulus)
UNIMPLEMENTED_NODE(Float64Negate)
UNIMPLEMENTED_NODE(Float64Equal)
UNIMPLEMENTED_NODE(Float64StrictEqual)
UNIMPLEMENTED_NODE(Float64LessThan)
@ -170,9 +163,7 @@ UNIMPLEMENTED_NODE(TruncateUint32ToInt32)
UNIMPLEMENTED_NODE(TruncateFloat64ToInt32)
UNIMPLEMENTED_NODE(Int32ToNumber)
UNIMPLEMENTED_NODE(Uint32ToNumber)
UNIMPLEMENTED_NODE(Float64Box)
UNIMPLEMENTED_NODE(HoleyFloat64Box)
UNIMPLEMENTED_NODE(CheckedFloat64Unbox)
UNIMPLEMENTED_NODE(LogicalNot)
UNIMPLEMENTED_NODE(SetPendingMessage)
UNIMPLEMENTED_NODE_WITH_CALL(StringAt)
@ -372,6 +363,97 @@ DEF_OPERATION(Int32GreaterThan)
DEF_OPERATION(Int32GreaterThanOrEqual)
#undef DEF_OPERATION
void Float64Add::SetValueLocationConstraints() {
UseRegister(left_input());
UseRegister(right_input());
DefineAsRegister(this);
}
void Float64Add::GenerateCode(MaglevAssembler* masm,
const ProcessingState& state) {
DoubleRegister left = ToDoubleRegister(left_input());
DoubleRegister right = ToDoubleRegister(right_input());
DoubleRegister out = ToDoubleRegister(result());
__ Fadd(out, left, right);
}
void Float64Subtract::SetValueLocationConstraints() {
UseRegister(left_input());
UseRegister(right_input());
DefineAsRegister(this);
}
void Float64Subtract::GenerateCode(MaglevAssembler* masm,
const ProcessingState& state) {
DoubleRegister left = ToDoubleRegister(left_input());
DoubleRegister right = ToDoubleRegister(right_input());
DoubleRegister out = ToDoubleRegister(result());
__ Fsub(out, left, right);
}
void Float64Multiply::SetValueLocationConstraints() {
UseRegister(left_input());
UseRegister(right_input());
DefineAsRegister(this);
}
void Float64Multiply::GenerateCode(MaglevAssembler* masm,
const ProcessingState& state) {
DoubleRegister left = ToDoubleRegister(left_input());
DoubleRegister right = ToDoubleRegister(right_input());
DoubleRegister out = ToDoubleRegister(result());
__ Fmul(out, left, right);
}
void Float64Divide::SetValueLocationConstraints() {
UseRegister(left_input());
UseRegister(right_input());
DefineAsRegister(this);
}
void Float64Divide::GenerateCode(MaglevAssembler* masm,
const ProcessingState& state) {
DoubleRegister left = ToDoubleRegister(left_input());
DoubleRegister right = ToDoubleRegister(right_input());
DoubleRegister out = ToDoubleRegister(result());
__ Fdiv(out, left, right);
}
int Float64Modulus::MaxCallStackArgs() const { return 0; }
void Float64Modulus::SetValueLocationConstraints() {
UseFixed(left_input(), v0);
UseFixed(right_input(), v1);
DefineSameAsFirst(this);
}
void Float64Modulus::GenerateCode(MaglevAssembler* masm,
const ProcessingState& state) {
AllowExternalCallThatCantCauseGC scope(masm);
__ CallCFunction(ExternalReference::mod_two_doubles_operation(), 0, 2);
}
void Float64Negate::SetValueLocationConstraints() {
UseRegister(input());
DefineAsRegister(this);
}
void Float64Negate::GenerateCode(MaglevAssembler* masm,
const ProcessingState& state) {
DoubleRegister value = ToDoubleRegister(input());
DoubleRegister out = ToDoubleRegister(result());
__ Fneg(out, value);
}
int Float64Exponentiate::MaxCallStackArgs() const { return 0; }
void Float64Exponentiate::SetValueLocationConstraints() {
UseFixed(left_input(), v0);
UseFixed(right_input(), v1);
DefineSameAsFirst(this);
}
void Float64Exponentiate::GenerateCode(MaglevAssembler* masm,
const ProcessingState& state) {
AllowExternalCallThatCantCauseGC scope(masm);
__ CallCFunction(ExternalReference::ieee754_pow_function(), 2);
}
void CheckInt32IsSmi::SetValueLocationConstraints() { UseRegister(input()); }
void CheckInt32IsSmi::GenerateCode(MaglevAssembler* masm,
const ProcessingState& state) {
@ -421,6 +503,44 @@ void UnsafeSmiTag::GenerateCode(MaglevAssembler* masm,
}
}
void Float64Box::SetValueLocationConstraints() {
UseRegister(input());
DefineAsRegister(this);
}
void Float64Box::GenerateCode(MaglevAssembler* masm,
const ProcessingState& state) {
DoubleRegister value = ToDoubleRegister(input());
Register object = ToRegister(result());
__ AllocateHeapNumber(register_snapshot(), object, value);
}
void CheckedFloat64Unbox::SetValueLocationConstraints() {
UseRegister(input());
DefineAsRegister(this);
}
void CheckedFloat64Unbox::GenerateCode(MaglevAssembler* masm,
const ProcessingState& state) {
Register value = ToRegister(input());
Label is_not_smi, done;
// Check if Smi.
__ JumpIfNotSmi(value, &is_not_smi);
// If Smi, convert to Float64.
UseScratchRegisterScope temps(masm);
Register temp = temps.AcquireX();
__ SmiToInt32(temp, value);
__ sxtw(temp, temp.W());
__ scvtf(ToDoubleRegister(result()), temp);
__ Jump(&done);
__ bind(&is_not_smi);
// Check if HeapNumber, deopt otherwise.
__ Move(temp, FieldMemOperand(value, HeapObject::kMapOffset));
__ CompareRoot(temp, RootIndex::kHeapNumberMap);
__ EmitEagerDeoptIf(ne, DeoptimizeReason::kNotANumber, this);
__ Move(temp, FieldMemOperand(value, HeapNumber::kValueOffset));
__ fmov(ToDoubleRegister(result()), temp);
__ bind(&done);
}
void IncreaseInterruptBudget::SetValueLocationConstraints() {}
void IncreaseInterruptBudget::GenerateCode(MaglevAssembler* masm,
const ProcessingState& state) {

View File

@ -1900,21 +1900,23 @@ class Float64BinaryNode : public FixedInputValueNodeT<2, Derived> {
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
};
#define DEF_FLOAT64_BINARY_NODE(Name) \
DEF_OPERATION_NODE(Float64##Name, Float64BinaryNode, Name)
DEF_FLOAT64_BINARY_NODE(Add)
DEF_FLOAT64_BINARY_NODE(Subtract)
DEF_FLOAT64_BINARY_NODE(Multiply)
DEF_FLOAT64_BINARY_NODE(Divide)
DEF_FLOAT64_BINARY_NODE(Modulus)
#undef DEF_FLOAT64_BINARY_NODE
#define DEF_OPERATION_NODE_WITH_CALL(Name, Super, OpName) \
class Name : public Super<Name, Operation::k##OpName> { \
using Base = Super<Name, Operation::k##OpName>; \
\
public: \
explicit Name(uint64_t bitfield) : Base(bitfield) {} \
int MaxCallStackArgs() const; \
void SetValueLocationConstraints(); \
void GenerateCode(MaglevAssembler*, const ProcessingState&); \
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {} \
};
class Float64Exponentiate
: public FixedInputValueNodeT<2, Float64Exponentiate> {
using Base = FixedInputValueNodeT<2, Float64Exponentiate>;
template <class Derived, Operation kOperation>
class Float64BinaryNodeWithCall : public FixedInputValueNodeT<2, Derived> {
using Base = FixedInputValueNodeT<2, Derived>;
public:
explicit Float64Exponentiate(uint64_t bitfield) : Base(bitfield) {}
static constexpr OpProperties kProperties =
OpProperties::Float64() | OpProperties::Call();
static constexpr typename Base::InputTypes kInputTypes{
@ -1925,12 +1927,31 @@ class Float64Exponentiate
Input& left_input() { return Node::input(kLeftIndex); }
Input& right_input() { return Node::input(kRightIndex); }
int MaxCallStackArgs() const;
void SetValueLocationConstraints();
void GenerateCode(MaglevAssembler*, const ProcessingState&);
protected:
explicit Float64BinaryNodeWithCall(uint64_t bitfield) : Base(bitfield) {}
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
};
#define DEF_FLOAT64_BINARY_NODE(Name) \
DEF_OPERATION_NODE(Float64##Name, Float64BinaryNode, Name)
#define DEF_FLOAT64_BINARY_NODE_WITH_CALL(Name) \
DEF_OPERATION_NODE_WITH_CALL(Float64##Name, Float64BinaryNodeWithCall, Name)
DEF_FLOAT64_BINARY_NODE(Add)
DEF_FLOAT64_BINARY_NODE(Subtract)
DEF_FLOAT64_BINARY_NODE(Multiply)
DEF_FLOAT64_BINARY_NODE(Divide)
#ifdef V8_TARGET_ARCH_ARM64
// On Arm64, floating point modulus is implemented with a call to a C++
// function, while on x64, it's implemented natively without call.
DEF_FLOAT64_BINARY_NODE_WITH_CALL(Modulus)
#else
DEF_FLOAT64_BINARY_NODE(Modulus)
#endif
DEF_FLOAT64_BINARY_NODE_WITH_CALL(Exponentiate)
#undef DEF_FLOAT64_BINARY_NODE
#undef DEF_FLOAT64_BINARY_NODE_WITH_CALL
template <class Derived, Operation kOperation>
class Float64CompareNode : public FixedInputValueNodeT<2, Derived> {
using Base = FixedInputValueNodeT<2, Derived>;
@ -1963,6 +1984,7 @@ DEF_FLOAT64_COMPARE_NODE(GreaterThanOrEqual)
#undef DEF_FLOAT64_COMPARE_NODE
#undef DEF_OPERATION_NODE
#undef DEF_OPERATION_NODE_WITH_CALL
class Float64Negate : public FixedInputValueNodeT<1, Float64Negate> {
using Base = FixedInputValueNodeT<1, Float64Negate>;