[turboshaft] Port operations from ECL to MachineLoweringReducer (2)
This CL ports operations from Turbofan's EffectControlLinearizer to Turboshaft's MachineLoweringReducer: - CheckedBigIntToBigInt64 - ChangeUint64ToBigInt Bug: v8:12783 Change-Id: I9386864305397642b840d2e89a6066a3263ce25d Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4198146 Reviewed-by: Darius Mercadier <dmercadier@chromium.org> Commit-Queue: Nico Hartmann <nicohartmann@chromium.org> Cr-Commit-Position: refs/heads/main@{#85519}
This commit is contained in:
parent
3c077cfe85
commit
a1ab842dbe
@ -1650,14 +1650,20 @@ CommonOperatorBuilder::CreateJSToWasmFrameStateFunctionInfo(
|
|||||||
const Operator* CommonOperatorBuilder::Chained(const Operator* op) {
|
const Operator* CommonOperatorBuilder::Chained(const Operator* op) {
|
||||||
// Use Chained only for operators that are not on the effect chain already.
|
// Use Chained only for operators that are not on the effect chain already.
|
||||||
DCHECK_EQ(op->EffectInputCount(), 0);
|
DCHECK_EQ(op->EffectInputCount(), 0);
|
||||||
|
DCHECK_EQ(op->ControlInputCount(), 0);
|
||||||
const char* mnemonic;
|
const char* mnemonic;
|
||||||
switch (op->opcode()) {
|
switch (op->opcode()) {
|
||||||
case IrOpcode::kChangeInt64ToBigInt:
|
case IrOpcode::kChangeInt64ToBigInt:
|
||||||
mnemonic = "Chained[ChangeInt64ToBigInt]";
|
mnemonic = "Chained[ChangeInt64ToBigInt]";
|
||||||
break;
|
break;
|
||||||
|
case IrOpcode::kChangeUint64ToBigInt:
|
||||||
|
mnemonic = "Chained[ChangeUint64ToBigInt]";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
// TODO(nicohartmann@): Need to store operator properties once we have to
|
||||||
|
// support Operator1 operators.
|
||||||
Operator::Properties properties = op->properties();
|
Operator::Properties properties = op->properties();
|
||||||
return zone()->New<Operator>(op->opcode(), properties, mnemonic,
|
return zone()->New<Operator>(op->opcode(), properties, mnemonic,
|
||||||
op->ValueInputCount(), 1, 1,
|
op->ValueInputCount(), 1, 1,
|
||||||
|
@ -1025,6 +1025,7 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
|
|||||||
result = LowerCheckedUint64ToInt64(node, frame_state);
|
result = LowerCheckedUint64ToInt64(node, frame_state);
|
||||||
break;
|
break;
|
||||||
case IrOpcode::kCheckedBigIntToBigInt64:
|
case IrOpcode::kCheckedBigIntToBigInt64:
|
||||||
|
if (v8_flags.turboshaft) return false;
|
||||||
result = LowerCheckedBigIntToBigInt64(node, frame_state);
|
result = LowerCheckedBigIntToBigInt64(node, frame_state);
|
||||||
break;
|
break;
|
||||||
case IrOpcode::kCheckInternalizedString:
|
case IrOpcode::kCheckInternalizedString:
|
||||||
@ -1144,7 +1145,16 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IrOpcode::kChangeUint64ToBigInt:
|
case IrOpcode::kChangeUint64ToBigInt:
|
||||||
result = LowerChangeUint64ToBigInt(node);
|
if (v8_flags.turboshaft) {
|
||||||
|
DCHECK(machine()->Is64());
|
||||||
|
// ChangeUint64ToBigInt is allocting when lowered, so we must fix its
|
||||||
|
// position in the effect chain such that it is non-floating after ECL
|
||||||
|
// and cannot mess up when rescheduling (e.g. in Turboshaft's graph
|
||||||
|
// builder).
|
||||||
|
result = gasm()->Chained(node->op(), node->InputAt(0));
|
||||||
|
} else {
|
||||||
|
result = LowerChangeUint64ToBigInt(node);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case IrOpcode::kTruncateBigIntToWord64:
|
case IrOpcode::kTruncateBigIntToWord64:
|
||||||
result = LowerTruncateBigIntToWord64(node);
|
result = LowerTruncateBigIntToWord64(node);
|
||||||
@ -3002,6 +3012,7 @@ Node* EffectControlLinearizer::LowerCheckBigInt(Node* node, Node* frame_state) {
|
|||||||
|
|
||||||
Node* EffectControlLinearizer::LowerCheckedBigIntToBigInt64(Node* node,
|
Node* EffectControlLinearizer::LowerCheckedBigIntToBigInt64(Node* node,
|
||||||
Node* frame_state) {
|
Node* frame_state) {
|
||||||
|
DCHECK(!v8_flags.turboshaft);
|
||||||
DCHECK(machine()->Is64());
|
DCHECK(machine()->Is64());
|
||||||
|
|
||||||
auto done = __ MakeLabel();
|
auto done = __ MakeLabel();
|
||||||
@ -3181,6 +3192,7 @@ Node* EffectControlLinearizer::LowerChangeInt64ToBigInt(Node* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Node* EffectControlLinearizer::LowerChangeUint64ToBigInt(Node* node) {
|
Node* EffectControlLinearizer::LowerChangeUint64ToBigInt(Node* node) {
|
||||||
|
DCHECK(!v8_flags.turboshaft);
|
||||||
DCHECK(machine()->Is64());
|
DCHECK(machine()->Is64());
|
||||||
|
|
||||||
auto done = __ MakeLabel(MachineRepresentation::kTagged);
|
auto done = __ MakeLabel(MachineRepresentation::kTagged);
|
||||||
|
@ -673,9 +673,16 @@ OpIndex GraphBuilder::Process(
|
|||||||
return assembler.Check(Map(node->InputAt(0)), dominating_frame_state,
|
return assembler.Check(Map(node->InputAt(0)), dominating_frame_state,
|
||||||
CheckOp::Kind::kCheckBigInt,
|
CheckOp::Kind::kCheckBigInt,
|
||||||
CheckParametersOf(op).feedback());
|
CheckParametersOf(op).feedback());
|
||||||
|
case IrOpcode::kCheckedBigIntToBigInt64:
|
||||||
|
return assembler.Check(Map(node->InputAt(0)), dominating_frame_state,
|
||||||
|
CheckOp::Kind::kBigIntIsBigInt64,
|
||||||
|
CheckParametersOf(op).feedback());
|
||||||
case IrOpcode::kChangeInt64ToBigInt:
|
case IrOpcode::kChangeInt64ToBigInt:
|
||||||
return assembler.ConvertToObject(
|
return assembler.ConvertToObject(
|
||||||
Map(node->InputAt(0)), ConvertToObjectOp::Kind::kInt64ToBigInt64);
|
Map(node->InputAt(0)), ConvertToObjectOp::Kind::kInt64ToBigInt64);
|
||||||
|
case IrOpcode::kChangeUint64ToBigInt:
|
||||||
|
return assembler.ConvertToObject(
|
||||||
|
Map(node->InputAt(0)), ConvertToObjectOp::Kind::kUint64ToBigInt64);
|
||||||
|
|
||||||
case IrOpcode::kSelect: {
|
case IrOpcode::kSelect: {
|
||||||
OpIndex cond = Map(node->InputAt(0));
|
OpIndex cond = Map(node->InputAt(0));
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "src/compiler/access-builder.h"
|
#include "src/compiler/access-builder.h"
|
||||||
#include "src/compiler/globals.h"
|
#include "src/compiler/globals.h"
|
||||||
#include "src/compiler/simplified-operator.h"
|
#include "src/compiler/simplified-operator.h"
|
||||||
|
#include "src/compiler/turboshaft/index.h"
|
||||||
#include "src/compiler/turboshaft/optimization-phase.h"
|
#include "src/compiler/turboshaft/optimization-phase.h"
|
||||||
#include "src/compiler/turboshaft/representations.h"
|
#include "src/compiler/turboshaft/representations.h"
|
||||||
#include "src/objects/bigint.h"
|
#include "src/objects/bigint.h"
|
||||||
@ -50,6 +51,55 @@ class MachineLoweringReducer : public Next {
|
|||||||
DeoptimizeReason::kWrongInstanceType, feedback);
|
DeoptimizeReason::kWrongInstanceType, feedback);
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
case CheckOp::Kind::kBigIntIsBigInt64: {
|
||||||
|
DCHECK(Asm().Is64());
|
||||||
|
|
||||||
|
Block* non_zero_block = Asm().NewBlock();
|
||||||
|
Block* done_block = Asm().NewBlock();
|
||||||
|
Block* maybe_out_of_range_block = Asm().NewBlock();
|
||||||
|
|
||||||
|
OpIndex bitfield = LoadField(input, AccessBuilder::ForBigIntBitfield());
|
||||||
|
Asm().Branch(Asm().Word32Equal(bitfield, Asm().Word32Constant(0)),
|
||||||
|
done_block, non_zero_block);
|
||||||
|
|
||||||
|
if (Asm().Bind(non_zero_block)) {
|
||||||
|
// Length must be 1.
|
||||||
|
OpIndex length_field = Asm().Word32BitwiseAnd(
|
||||||
|
bitfield, Asm().Word32Constant(BigInt::LengthBits::kMask));
|
||||||
|
Asm().DeoptimizeIfNot(
|
||||||
|
Asm().Word32Equal(length_field,
|
||||||
|
Asm().Word32Constant(
|
||||||
|
uint32_t{1} << BigInt::LengthBits::kShift)),
|
||||||
|
frame_state, DeoptimizeReason::kNotABigInt64, feedback);
|
||||||
|
|
||||||
|
// Check if it fits in 64 bit signed int.
|
||||||
|
OpIndex lsd = LoadField(
|
||||||
|
input, AccessBuilder::ForBigIntLeastSignificantDigit64());
|
||||||
|
OpIndex magnitude_check = Asm().Uint64LessThanOrEqual(
|
||||||
|
lsd, Asm().Word64Constant(std::numeric_limits<int64_t>::max()));
|
||||||
|
Asm().Branch(magnitude_check, done_block, maybe_out_of_range_block);
|
||||||
|
|
||||||
|
if (Asm().Bind(maybe_out_of_range_block)) {
|
||||||
|
// The BigInt probably doesn't fit into signed int64. The only
|
||||||
|
// exception is int64_t::min. We check for this.
|
||||||
|
OpIndex sign = Asm().Word32BitwiseAnd(
|
||||||
|
bitfield, Asm().Word32Constant(BigInt::SignBits::kMask));
|
||||||
|
OpIndex sign_check = Asm().Word32Equal(
|
||||||
|
sign, Asm().Word32Constant(BigInt::SignBits::kMask));
|
||||||
|
Asm().DeoptimizeIfNot(sign_check, frame_state,
|
||||||
|
DeoptimizeReason::kNotABigInt64, feedback);
|
||||||
|
|
||||||
|
OpIndex min_check = Asm().Word64Equal(
|
||||||
|
lsd, Asm().Word64Constant(std::numeric_limits<int64_t>::min()));
|
||||||
|
Asm().DeoptimizeIfNot(min_check, frame_state,
|
||||||
|
DeoptimizeReason::kNotABigInt64, feedback);
|
||||||
|
Asm().Goto(done_block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Asm().BindReachable(done_block);
|
||||||
|
return input;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
@ -63,7 +113,7 @@ class MachineLoweringReducer : public Next {
|
|||||||
// BigInts with value 0 must be of size 0 (canonical form).
|
// BigInts with value 0 must be of size 0 (canonical form).
|
||||||
Block* non_zero_block = Asm().NewBlock();
|
Block* non_zero_block = Asm().NewBlock();
|
||||||
Block* zero_block = Asm().NewBlock();
|
Block* zero_block = Asm().NewBlock();
|
||||||
Block* merge_block = Asm().NewBlock();
|
Block* done_block = Asm().NewBlock();
|
||||||
|
|
||||||
Variable result =
|
Variable result =
|
||||||
Asm().NewFreshVariable(RegisterRepresentation::Tagged());
|
Asm().NewFreshVariable(RegisterRepresentation::Tagged());
|
||||||
@ -74,7 +124,7 @@ class MachineLoweringReducer : public Next {
|
|||||||
if (Asm().Bind(zero_block)) {
|
if (Asm().Bind(zero_block)) {
|
||||||
Asm().Set(result, BuildAllocateBigInt(OpIndex::Invalid(),
|
Asm().Set(result, BuildAllocateBigInt(OpIndex::Invalid(),
|
||||||
OpIndex::Invalid()));
|
OpIndex::Invalid()));
|
||||||
Asm().Goto(merge_block);
|
Asm().Goto(done_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Asm().Bind(non_zero_block)) {
|
if (Asm().Bind(non_zero_block)) {
|
||||||
@ -92,10 +142,41 @@ class MachineLoweringReducer : public Next {
|
|||||||
OpIndex absolute_value = Asm().Word64Sub(
|
OpIndex absolute_value = Asm().Word64Sub(
|
||||||
Asm().Word64BitwiseXor(input, sign_mask), sign_mask);
|
Asm().Word64BitwiseXor(input, sign_mask), sign_mask);
|
||||||
Asm().Set(result, BuildAllocateBigInt(bitfield, absolute_value));
|
Asm().Set(result, BuildAllocateBigInt(bitfield, absolute_value));
|
||||||
Asm().Goto(merge_block);
|
Asm().Goto(done_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
Asm().BindReachable(merge_block);
|
Asm().BindReachable(done_block);
|
||||||
|
return Asm().Get(result);
|
||||||
|
}
|
||||||
|
case ConvertToObjectOp::Kind::kUint64ToBigInt64: {
|
||||||
|
DCHECK(Asm().Is64());
|
||||||
|
|
||||||
|
// BigInts with value 0 must be of size 0 (canonical form).
|
||||||
|
Block* non_zero_block = Asm().NewBlock();
|
||||||
|
Block* zero_block = Asm().NewBlock();
|
||||||
|
Block* done_block = Asm().NewBlock();
|
||||||
|
|
||||||
|
Variable result =
|
||||||
|
Asm().NewFreshVariable(RegisterRepresentation::Tagged());
|
||||||
|
|
||||||
|
Asm().Branch(
|
||||||
|
Asm().Word64Equal(input, Asm().Word64Constant(uint64_t{0})),
|
||||||
|
zero_block, non_zero_block);
|
||||||
|
|
||||||
|
if (Asm().Bind(zero_block)) {
|
||||||
|
Asm().Set(result, BuildAllocateBigInt(OpIndex::Invalid(),
|
||||||
|
OpIndex::Invalid()));
|
||||||
|
Asm().Goto(done_block);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Asm().Bind(non_zero_block)) {
|
||||||
|
const auto bitfield = BigInt::LengthBits::encode(1);
|
||||||
|
Asm().Set(result,
|
||||||
|
BuildAllocateBigInt(Asm().Word32Constant(bitfield), input));
|
||||||
|
Asm().Goto(done_block);
|
||||||
|
}
|
||||||
|
|
||||||
|
Asm().BindReachable(done_block);
|
||||||
return Asm().Get(result);
|
return Asm().Get(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -599,6 +599,8 @@ std::ostream& operator<<(std::ostream& os, CheckOp::Kind kind) {
|
|||||||
switch (kind) {
|
switch (kind) {
|
||||||
case CheckOp::Kind::kCheckBigInt:
|
case CheckOp::Kind::kCheckBigInt:
|
||||||
return os << "CheckBigInt";
|
return os << "CheckBigInt";
|
||||||
|
case CheckOp::Kind::kBigIntIsBigInt64:
|
||||||
|
return os << "BigIntIsBigInt64";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,6 +608,8 @@ std::ostream& operator<<(std::ostream& os, ConvertToObjectOp::Kind kind) {
|
|||||||
switch (kind) {
|
switch (kind) {
|
||||||
case ConvertToObjectOp::Kind::kInt64ToBigInt64:
|
case ConvertToObjectOp::Kind::kInt64ToBigInt64:
|
||||||
return os << "Int64ToBigInt64";
|
return os << "Int64ToBigInt64";
|
||||||
|
case ConvertToObjectOp::Kind::kUint64ToBigInt64:
|
||||||
|
return os << "Uint64ToBigInt64";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2120,7 +2120,8 @@ struct CheckTurboshaftTypeOfOp
|
|||||||
|
|
||||||
struct CheckOp : FixedArityOperationT<2, CheckOp> {
|
struct CheckOp : FixedArityOperationT<2, CheckOp> {
|
||||||
enum class Kind {
|
enum class Kind {
|
||||||
kCheckBigInt,
|
kCheckBigInt, // Checks if a tagged input is a BigInt object
|
||||||
|
kBigIntIsBigInt64, // Checks if a BigInt input is in BigInt64 range
|
||||||
};
|
};
|
||||||
Kind kind;
|
Kind kind;
|
||||||
FeedbackSource feedback;
|
FeedbackSource feedback;
|
||||||
@ -2155,15 +2156,13 @@ struct IsSmiTaggedOp : FixedArityOperationT<1, IsSmiTaggedOp> {
|
|||||||
struct ConvertToObjectOp : FixedArityOperationT<1, ConvertToObjectOp> {
|
struct ConvertToObjectOp : FixedArityOperationT<1, ConvertToObjectOp> {
|
||||||
enum class Kind {
|
enum class Kind {
|
||||||
kInt64ToBigInt64,
|
kInt64ToBigInt64,
|
||||||
|
kUint64ToBigInt64,
|
||||||
};
|
};
|
||||||
Kind kind;
|
Kind kind;
|
||||||
|
|
||||||
static constexpr OpProperties properties = OpProperties::PureMayAllocate();
|
static constexpr OpProperties properties = OpProperties::PureMayAllocate();
|
||||||
base::Vector<const RegisterRepresentation> outputs_rep() const {
|
base::Vector<const RegisterRepresentation> outputs_rep() const {
|
||||||
switch (kind) {
|
return RepVector<RegisterRepresentation::Tagged()>();
|
||||||
case Kind::kInt64ToBigInt64:
|
|
||||||
return RepVector<RegisterRepresentation::Tagged()>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OpIndex input() const { return Base::input(0); }
|
OpIndex input() const { return Base::input(0); }
|
||||||
|
Loading…
Reference in New Issue
Block a user