[turboshaft] some IR refactorings
- Remove TruncateInt64ToInt32 instead of translating to Turboshaft, since it has no effect. Removing it simplifies pattern-matching in optimizations. - Change how exception handling is done in Turboshaft: The exception value is obtained as the result of `CatchExceptionOp` instead of a special projection. This simplifies projections. - Add `TupleOp` as the counterpart to `ProjectionOp`, which is useful for lowerings of operations that have multiple outputs. - Split BinopOp into WordBinopOp and FloatBinopOp because they have quite different semantics and many kinds only exist for one of them. - rename IntegerUnary to WordUnary and other occurences of Integer/Integral - rename ChangeOp::Kind::kUnsignedFloatTruncate` to `kJSFloatTruncate` because it actually has JS wrap-around semantics. - move/add representation DCHECKs to operation constructors. - add some convinience helpers to `AssemblerInterface`. - Add a mechanism to check which operations are supported by the machine. Drive-by fix: Abort current block in OptimizationPhase::VisitBlock if we lower to a block-terminator. Bug: v8:12783 Change-Id: Ib738accccd22fb1606d9dab86f57ac1e739fcec2 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3857449 Auto-Submit: Tobias Tebbi <tebbi@chromium.org> Reviewed-by: Darius Mercadier <dmercadier@chromium.org> Commit-Queue: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/main@{#82857}
This commit is contained in:
parent
156c302fda
commit
7a61dad0db
@ -2876,6 +2876,7 @@ filegroup(
|
||||
"src/compiler/turboshaft/recreate-schedule.cc",
|
||||
"src/compiler/turboshaft/recreate-schedule.h",
|
||||
"src/compiler/turboshaft/sidetable.h",
|
||||
"src/compiler/turboshaft/utils.h",
|
||||
"src/compiler/turboshaft/value-numbering-assembler.h",
|
||||
"src/compiler/type-cache.cc",
|
||||
"src/compiler/type-cache.h",
|
||||
|
1
BUILD.gn
1
BUILD.gn
@ -2995,6 +2995,7 @@ v8_header_set("v8_internal_headers") {
|
||||
"src/compiler/turboshaft/optimization-phase.h",
|
||||
"src/compiler/turboshaft/recreate-schedule.h",
|
||||
"src/compiler/turboshaft/sidetable.h",
|
||||
"src/compiler/turboshaft/utils.h",
|
||||
"src/compiler/turboshaft/value-numbering-assembler.h",
|
||||
"src/compiler/type-cache.h",
|
||||
"src/compiler/type-narrowing-reducer.h",
|
||||
|
@ -2013,6 +2013,8 @@ void InstructionSelector::VisitChangeInt32ToInt64(Node* node) {
|
||||
immediate_mode = kLoadStoreImm16;
|
||||
break;
|
||||
case MachineRepresentation::kWord32:
|
||||
case MachineRepresentation::kTaggedSigned:
|
||||
case MachineRepresentation::kTagged:
|
||||
opcode = kArm64Ldrsw;
|
||||
immediate_mode = kLoadStoreImm32;
|
||||
break;
|
||||
|
@ -1657,6 +1657,8 @@ void InstructionSelector::VisitChangeInt32ToInt64(Node* node) {
|
||||
opcode = load_rep.IsSigned() ? kX64Movsxwq : kX64Movzxwq;
|
||||
break;
|
||||
case MachineRepresentation::kWord32:
|
||||
case MachineRepresentation::kTaggedSigned:
|
||||
case MachineRepresentation::kTagged:
|
||||
// ChangeInt32ToInt64 must interpret its input as a _signed_ 32-bit
|
||||
// integer, so here we must sign-extend the loaded value in any case.
|
||||
opcode = kX64Movsxlq;
|
||||
|
@ -112,7 +112,7 @@ class V8_EXPORT_PRIVATE JSGraph : public MachineGraph {
|
||||
// Cached global node accessor methods.
|
||||
#define DECLARE_GETTER(name) Node* name();
|
||||
CACHED_GLOBAL_LIST(DECLARE_GETTER)
|
||||
#undef DECLARE_FIELD
|
||||
#undef DECLARE_GETTER
|
||||
|
||||
private:
|
||||
Isolate* isolate_;
|
||||
|
@ -32,132 +32,248 @@ class AssemblerInterface : public Superclass {
|
||||
using Superclass::Superclass;
|
||||
using Base = Superclass;
|
||||
|
||||
OpIndex Add(OpIndex left, OpIndex right, MachineRepresentation rep) {
|
||||
return subclass().Binop(left, right, BinopOp::Kind::kAdd, rep);
|
||||
#define DECL_MULTI_REP_BINOP(name, operation, kind) \
|
||||
OpIndex name(OpIndex left, OpIndex right, MachineRepresentation rep) { \
|
||||
return subclass().operation(left, right, operation##Op::Kind::k##kind, \
|
||||
rep); \
|
||||
}
|
||||
OpIndex AddWithOverflow(OpIndex left, OpIndex right,
|
||||
MachineRepresentation rep) {
|
||||
DCHECK(rep == MachineRepresentation::kWord32 ||
|
||||
rep == MachineRepresentation::kWord64);
|
||||
return subclass().OverflowCheckedBinop(
|
||||
left, right, OverflowCheckedBinopOp::Kind::kSignedAdd, rep);
|
||||
#define DECL_SINGLE_REP_BINOP(name, operation, kind, rep) \
|
||||
OpIndex name(OpIndex left, OpIndex right) { \
|
||||
return subclass().operation(left, right, operation##Op::Kind::k##kind, \
|
||||
MachineRepresentation::k##rep); \
|
||||
}
|
||||
OpIndex Sub(OpIndex left, OpIndex right, MachineRepresentation rep) {
|
||||
return subclass().Binop(left, right, BinopOp::Kind::kSub, rep);
|
||||
#define DECL_SINGLE_REP_BINOP_NO_KIND(name, operation, rep) \
|
||||
OpIndex name(OpIndex left, OpIndex right) { \
|
||||
return subclass().operation(left, right, MachineRepresentation::k##rep); \
|
||||
}
|
||||
OpIndex SubWithOverflow(OpIndex left, OpIndex right,
|
||||
MachineRepresentation rep) {
|
||||
return subclass().OverflowCheckedBinop(
|
||||
left, right, OverflowCheckedBinopOp::Kind::kSignedSub, rep);
|
||||
}
|
||||
OpIndex Mul(OpIndex left, OpIndex right, MachineRepresentation rep) {
|
||||
return subclass().Binop(left, right, BinopOp::Kind::kMul, rep);
|
||||
}
|
||||
OpIndex SignedMulOverflownBits(OpIndex left, OpIndex right,
|
||||
MachineRepresentation rep) {
|
||||
return subclass().Binop(left, right, BinopOp::Kind::kSignedMulOverflownBits,
|
||||
rep);
|
||||
}
|
||||
OpIndex UnsignedMulOverflownBits(OpIndex left, OpIndex right,
|
||||
MachineRepresentation rep) {
|
||||
return subclass().Binop(left, right,
|
||||
BinopOp::Kind::kUnsignedMulOverflownBits, rep);
|
||||
}
|
||||
OpIndex MulWithOverflow(OpIndex left, OpIndex right,
|
||||
MachineRepresentation rep) {
|
||||
DCHECK(rep == MachineRepresentation::kWord32 ||
|
||||
rep == MachineRepresentation::kWord64);
|
||||
return subclass().OverflowCheckedBinop(
|
||||
left, right, OverflowCheckedBinopOp::Kind::kSignedMul, rep);
|
||||
}
|
||||
OpIndex SignedDiv(OpIndex left, OpIndex right, MachineRepresentation rep) {
|
||||
return subclass().Binop(left, right, BinopOp::Kind::kSignedDiv, rep);
|
||||
}
|
||||
OpIndex UnsignedDiv(OpIndex left, OpIndex right, MachineRepresentation rep) {
|
||||
return subclass().Binop(left, right, BinopOp::Kind::kUnsignedDiv, rep);
|
||||
}
|
||||
OpIndex SignedMod(OpIndex left, OpIndex right, MachineRepresentation rep) {
|
||||
return subclass().Binop(left, right, BinopOp::Kind::kSignedMod, rep);
|
||||
}
|
||||
OpIndex UnsignedMod(OpIndex left, OpIndex right, MachineRepresentation rep) {
|
||||
return subclass().Binop(left, right, BinopOp::Kind::kUnsignedMod, rep);
|
||||
}
|
||||
OpIndex BitwiseAnd(OpIndex left, OpIndex right, MachineRepresentation rep) {
|
||||
DCHECK(rep == MachineRepresentation::kWord32 ||
|
||||
rep == MachineRepresentation::kWord64);
|
||||
return subclass().Binop(left, right, BinopOp::Kind::kBitwiseAnd, rep);
|
||||
}
|
||||
OpIndex BitwiseOr(OpIndex left, OpIndex right, MachineRepresentation rep) {
|
||||
DCHECK(rep == MachineRepresentation::kWord32 ||
|
||||
rep == MachineRepresentation::kWord64);
|
||||
return subclass().Binop(left, right, BinopOp::Kind::kBitwiseOr, rep);
|
||||
}
|
||||
OpIndex Min(OpIndex left, OpIndex right, MachineRepresentation rep) {
|
||||
DCHECK_EQ(rep, MachineRepresentation::kFloat64);
|
||||
return subclass().Binop(left, right, BinopOp::Kind::kMin, rep);
|
||||
}
|
||||
OpIndex Max(OpIndex left, OpIndex right, MachineRepresentation rep) {
|
||||
DCHECK_EQ(rep, MachineRepresentation::kFloat64);
|
||||
return subclass().Binop(left, right, BinopOp::Kind::kMax, rep);
|
||||
}
|
||||
OpIndex Power(OpIndex left, OpIndex right, MachineRepresentation rep) {
|
||||
DCHECK_EQ(rep, MachineRepresentation::kFloat64);
|
||||
return subclass().Binop(left, right, BinopOp::Kind::kPower, rep);
|
||||
}
|
||||
OpIndex Atan2(OpIndex left, OpIndex right, MachineRepresentation rep) {
|
||||
DCHECK_EQ(rep, MachineRepresentation::kFloat64);
|
||||
return subclass().Binop(left, right, BinopOp::Kind::kAtan2, rep);
|
||||
}
|
||||
OpIndex BitwiseXor(OpIndex left, OpIndex right, MachineRepresentation rep) {
|
||||
DCHECK(rep == MachineRepresentation::kWord32 ||
|
||||
rep == MachineRepresentation::kWord64);
|
||||
return subclass().Binop(left, right, BinopOp::Kind::kBitwiseXor, rep);
|
||||
}
|
||||
OpIndex ShiftLeft(OpIndex left, OpIndex right, MachineRepresentation rep) {
|
||||
DCHECK(rep == MachineRepresentation::kWord32 ||
|
||||
rep == MachineRepresentation::kWord64);
|
||||
return subclass().Shift(left, right, ShiftOp::Kind::kShiftLeft, rep);
|
||||
}
|
||||
OpIndex ShiftRightArithmetic(OpIndex left, OpIndex right,
|
||||
MachineRepresentation rep) {
|
||||
DCHECK(rep == MachineRepresentation::kWord32 ||
|
||||
rep == MachineRepresentation::kWord64);
|
||||
return subclass().Shift(left, right, ShiftOp::Kind::kShiftRightArithmetic,
|
||||
rep);
|
||||
}
|
||||
OpIndex ShiftRightArithmeticShiftOutZeros(OpIndex left, OpIndex right,
|
||||
MachineRepresentation rep) {
|
||||
DCHECK(rep == MachineRepresentation::kWord32 ||
|
||||
rep == MachineRepresentation::kWord64);
|
||||
return subclass().Shift(
|
||||
left, right, ShiftOp::Kind::kShiftRightArithmeticShiftOutZeros, rep);
|
||||
}
|
||||
OpIndex ShiftRightLogical(OpIndex left, OpIndex right,
|
||||
DECL_MULTI_REP_BINOP(WordAdd, WordBinop, Add)
|
||||
DECL_SINGLE_REP_BINOP(Word32Add, WordBinop, Add, Word32)
|
||||
DECL_SINGLE_REP_BINOP(Word64Add, WordBinop, Add, Word64)
|
||||
|
||||
DECL_MULTI_REP_BINOP(WordMul, WordBinop, Mul)
|
||||
DECL_SINGLE_REP_BINOP(Word32Mul, WordBinop, Mul, Word32)
|
||||
DECL_SINGLE_REP_BINOP(Word64Mul, WordBinop, Mul, Word64)
|
||||
|
||||
DECL_MULTI_REP_BINOP(WordBitwiseAnd, WordBinop, BitwiseAnd)
|
||||
DECL_SINGLE_REP_BINOP(Word32BitwiseAnd, WordBinop, BitwiseAnd, Word32)
|
||||
DECL_SINGLE_REP_BINOP(Word64BitwiseAnd, WordBinop, BitwiseAnd, Word64)
|
||||
|
||||
DECL_MULTI_REP_BINOP(WordBitwiseOr, WordBinop, BitwiseOr)
|
||||
DECL_SINGLE_REP_BINOP(Word32BitwiseOr, WordBinop, BitwiseOr, Word32)
|
||||
DECL_SINGLE_REP_BINOP(Word64BitwiseOr, WordBinop, BitwiseOr, Word64)
|
||||
|
||||
DECL_MULTI_REP_BINOP(WordBitwiseXor, WordBinop, BitwiseXor)
|
||||
DECL_SINGLE_REP_BINOP(Word32BitwiseXor, WordBinop, BitwiseXor, Word32)
|
||||
DECL_SINGLE_REP_BINOP(Word64BitwiseXor, WordBinop, BitwiseXor, Word64)
|
||||
|
||||
DECL_MULTI_REP_BINOP(WordSub, WordBinop, Sub)
|
||||
DECL_SINGLE_REP_BINOP(Word32Sub, WordBinop, Sub, Word32)
|
||||
DECL_SINGLE_REP_BINOP(Word64Sub, WordBinop, Sub, Word64)
|
||||
|
||||
DECL_MULTI_REP_BINOP(IntDiv, WordBinop, SignedDiv)
|
||||
DECL_SINGLE_REP_BINOP(Int32Div, WordBinop, SignedDiv, Word32)
|
||||
DECL_SINGLE_REP_BINOP(Int64Div, WordBinop, SignedDiv, Word64)
|
||||
DECL_MULTI_REP_BINOP(UintDiv, WordBinop, UnsignedDiv)
|
||||
DECL_SINGLE_REP_BINOP(Uint32Div, WordBinop, UnsignedDiv, Word32)
|
||||
DECL_SINGLE_REP_BINOP(Uint64Div, WordBinop, UnsignedDiv, Word64)
|
||||
DECL_MULTI_REP_BINOP(IntMod, WordBinop, SignedMod)
|
||||
DECL_SINGLE_REP_BINOP(Int32Mod, WordBinop, SignedMod, Word32)
|
||||
DECL_SINGLE_REP_BINOP(Int64Mod, WordBinop, SignedMod, Word64)
|
||||
DECL_MULTI_REP_BINOP(UintMod, WordBinop, UnsignedMod)
|
||||
DECL_SINGLE_REP_BINOP(Uint32Mod, WordBinop, UnsignedMod, Word32)
|
||||
DECL_SINGLE_REP_BINOP(Uint64Mod, WordBinop, UnsignedMod, Word64)
|
||||
DECL_SINGLE_REP_BINOP(Int32MulOverflownBits, WordBinop,
|
||||
SignedMulOverflownBits, Word32)
|
||||
DECL_SINGLE_REP_BINOP(Uint32MulOverflownBits, WordBinop,
|
||||
UnsignedMulOverflownBits, Word32)
|
||||
|
||||
DECL_MULTI_REP_BINOP(IntAddCheckOverflow, OverflowCheckedBinop, SignedAdd)
|
||||
DECL_SINGLE_REP_BINOP(Int32AddCheckOverflow, OverflowCheckedBinop, SignedAdd,
|
||||
Word32)
|
||||
DECL_SINGLE_REP_BINOP(Int64AddCheckOverflow, OverflowCheckedBinop, SignedAdd,
|
||||
Word64)
|
||||
DECL_MULTI_REP_BINOP(IntSubCheckOverflow, OverflowCheckedBinop, SignedSub)
|
||||
DECL_SINGLE_REP_BINOP(Int32SubCheckOverflow, OverflowCheckedBinop, SignedSub,
|
||||
Word32)
|
||||
DECL_SINGLE_REP_BINOP(Int64SubCheckOverflow, OverflowCheckedBinop, SignedSub,
|
||||
Word64)
|
||||
DECL_MULTI_REP_BINOP(IntMulCheckOverflow, OverflowCheckedBinop, SignedMul)
|
||||
DECL_SINGLE_REP_BINOP(Int32MulCheckOverflow, OverflowCheckedBinop, SignedMul,
|
||||
Word32)
|
||||
DECL_SINGLE_REP_BINOP(Int64MulCheckOverflow, OverflowCheckedBinop, SignedMul,
|
||||
Word64)
|
||||
|
||||
DECL_MULTI_REP_BINOP(FloatAdd, FloatBinop, Add)
|
||||
DECL_SINGLE_REP_BINOP(Float32Add, FloatBinop, Add, Float32)
|
||||
DECL_SINGLE_REP_BINOP(Float64Add, FloatBinop, Add, Float64)
|
||||
DECL_MULTI_REP_BINOP(FloatMul, FloatBinop, Mul)
|
||||
DECL_SINGLE_REP_BINOP(Float32Mul, FloatBinop, Mul, Float32)
|
||||
DECL_SINGLE_REP_BINOP(Float64Mul, FloatBinop, Mul, Float64)
|
||||
DECL_MULTI_REP_BINOP(FloatSub, FloatBinop, Sub)
|
||||
DECL_SINGLE_REP_BINOP(Float32Sub, FloatBinop, Sub, Float32)
|
||||
DECL_SINGLE_REP_BINOP(Float64Sub, FloatBinop, Sub, Float64)
|
||||
DECL_MULTI_REP_BINOP(FloatDiv, FloatBinop, Div)
|
||||
DECL_SINGLE_REP_BINOP(Float32Div, FloatBinop, Div, Float32)
|
||||
DECL_SINGLE_REP_BINOP(Float64Div, FloatBinop, Div, Float64)
|
||||
DECL_MULTI_REP_BINOP(FloatMin, FloatBinop, Min)
|
||||
DECL_SINGLE_REP_BINOP(Float32Min, FloatBinop, Min, Float32)
|
||||
DECL_SINGLE_REP_BINOP(Float64Min, FloatBinop, Min, Float64)
|
||||
DECL_MULTI_REP_BINOP(FloatMax, FloatBinop, Max)
|
||||
DECL_SINGLE_REP_BINOP(Float32Max, FloatBinop, Max, Float32)
|
||||
DECL_SINGLE_REP_BINOP(Float64Max, FloatBinop, Max, Float64)
|
||||
DECL_SINGLE_REP_BINOP(Float64Mod, FloatBinop, Mod, Float64)
|
||||
DECL_SINGLE_REP_BINOP(Float64Power, FloatBinop, Power, Float64)
|
||||
DECL_SINGLE_REP_BINOP(Float64Atan2, FloatBinop, Atan2, Float64)
|
||||
|
||||
DECL_MULTI_REP_BINOP(ShiftRightArithmeticShiftOutZeros, Shift,
|
||||
ShiftRightArithmeticShiftOutZeros)
|
||||
DECL_SINGLE_REP_BINOP(Word32ShiftRightArithmeticShiftOutZeros, Shift,
|
||||
ShiftRightArithmeticShiftOutZeros, Word32)
|
||||
DECL_SINGLE_REP_BINOP(Word64ShiftRightArithmeticShiftOutZeros, Shift,
|
||||
ShiftRightArithmeticShiftOutZeros, Word64)
|
||||
DECL_MULTI_REP_BINOP(ShiftRightArithmetic, Shift, ShiftRightArithmetic)
|
||||
DECL_SINGLE_REP_BINOP(Word32ShiftRightArithmetic, Shift, ShiftRightArithmetic,
|
||||
Word32)
|
||||
DECL_SINGLE_REP_BINOP(Word64ShiftRightArithmetic, Shift, ShiftRightArithmetic,
|
||||
Word64)
|
||||
DECL_MULTI_REP_BINOP(ShiftRightLogical, Shift, ShiftRightLogical)
|
||||
DECL_SINGLE_REP_BINOP(Word32ShiftRightLogical, Shift, ShiftRightLogical,
|
||||
Word32)
|
||||
DECL_SINGLE_REP_BINOP(Word64ShiftRightLogical, Shift, ShiftRightLogical,
|
||||
Word64)
|
||||
DECL_MULTI_REP_BINOP(ShiftLeft, Shift, ShiftLeft)
|
||||
DECL_SINGLE_REP_BINOP(Word32ShiftLeft, Shift, ShiftLeft, Word32)
|
||||
DECL_SINGLE_REP_BINOP(Word64ShiftLeft, Shift, ShiftLeft, Word64)
|
||||
DECL_MULTI_REP_BINOP(RotateRight, Shift, RotateRight)
|
||||
DECL_SINGLE_REP_BINOP(Word32RotateRight, Shift, RotateRight, Word32)
|
||||
DECL_SINGLE_REP_BINOP(Word64RotateRight, Shift, RotateRight, Word64)
|
||||
DECL_MULTI_REP_BINOP(RotateLeft, Shift, RotateLeft)
|
||||
DECL_SINGLE_REP_BINOP(Word32RotateLeft, Shift, RotateLeft, Word32)
|
||||
DECL_SINGLE_REP_BINOP(Word64RotateLeft, Shift, RotateLeft, Word64)
|
||||
|
||||
OpIndex ShiftRightLogical(OpIndex left, uint32_t right,
|
||||
MachineRepresentation rep) {
|
||||
DCHECK(rep == MachineRepresentation::kWord32 ||
|
||||
rep == MachineRepresentation::kWord64);
|
||||
return subclass().Shift(left, right, ShiftOp::Kind::kShiftRightLogical,
|
||||
rep);
|
||||
DCHECK_GE(right, 0);
|
||||
DCHECK_LT(right, ElementSizeInBits(rep));
|
||||
return ShiftRightLogical(left, Word32Constant(right), rep);
|
||||
}
|
||||
OpIndex RotateLeft(OpIndex left, OpIndex right, MachineRepresentation rep) {
|
||||
DCHECK(rep == MachineRepresentation::kWord32 ||
|
||||
rep == MachineRepresentation::kWord64);
|
||||
return subclass().Shift(left, right, ShiftOp::Kind::kRotateLeft, rep);
|
||||
OpIndex ShiftRightArithmetic(OpIndex left, uint32_t right,
|
||||
MachineRepresentation rep) {
|
||||
DCHECK_GE(right, 0);
|
||||
DCHECK_LT(right, ElementSizeInBits(rep));
|
||||
return ShiftRightArithmetic(left, Word32Constant(right), rep);
|
||||
}
|
||||
OpIndex RotateRight(OpIndex left, OpIndex right, MachineRepresentation rep) {
|
||||
DCHECK(rep == MachineRepresentation::kWord32 ||
|
||||
rep == MachineRepresentation::kWord64);
|
||||
return subclass().Shift(left, right, ShiftOp::Kind::kRotateRight, rep);
|
||||
|
||||
DECL_SINGLE_REP_BINOP_NO_KIND(Word32Equal, Equal, Word32)
|
||||
DECL_SINGLE_REP_BINOP_NO_KIND(Word64Equal, Equal, Word64)
|
||||
DECL_SINGLE_REP_BINOP_NO_KIND(Float32Equal, Equal, Float32)
|
||||
DECL_SINGLE_REP_BINOP_NO_KIND(Float64Equal, Equal, Float64)
|
||||
|
||||
DECL_MULTI_REP_BINOP(IntLessThan, Comparison, SignedLessThan)
|
||||
DECL_SINGLE_REP_BINOP(Int32LessThan, Comparison, SignedLessThan, Word32)
|
||||
DECL_SINGLE_REP_BINOP(Int64LessThan, Comparison, SignedLessThan, Word64)
|
||||
DECL_MULTI_REP_BINOP(UintLessThan, Comparison, UnsignedLessThan)
|
||||
DECL_SINGLE_REP_BINOP(Uint32LessThan, Comparison, UnsignedLessThan, Word32)
|
||||
DECL_SINGLE_REP_BINOP(Uint64LessThan, Comparison, UnsignedLessThan, Word64)
|
||||
DECL_MULTI_REP_BINOP(FloatLessThan, Comparison, SignedLessThan)
|
||||
DECL_SINGLE_REP_BINOP(Float32LessThan, Comparison, SignedLessThan, Float32)
|
||||
DECL_SINGLE_REP_BINOP(Float64LessThan, Comparison, SignedLessThan, Float64)
|
||||
|
||||
DECL_MULTI_REP_BINOP(IntLessThanOrEqual, Comparison, SignedLessThanOrEqual)
|
||||
DECL_SINGLE_REP_BINOP(Int32LessThanOrEqual, Comparison, SignedLessThanOrEqual,
|
||||
Word32)
|
||||
DECL_SINGLE_REP_BINOP(Int64LessThanOrEqual, Comparison, SignedLessThanOrEqual,
|
||||
Word64)
|
||||
DECL_MULTI_REP_BINOP(UintLessThanOrEqual, Comparison, UnsignedLessThanOrEqual)
|
||||
DECL_SINGLE_REP_BINOP(Uint32LessThanOrEqual, Comparison,
|
||||
UnsignedLessThanOrEqual, Word32)
|
||||
DECL_SINGLE_REP_BINOP(Uint64LessThanOrEqual, Comparison,
|
||||
UnsignedLessThanOrEqual, Word64)
|
||||
DECL_MULTI_REP_BINOP(FloatLessThanOrEqual, Comparison, SignedLessThanOrEqual)
|
||||
DECL_SINGLE_REP_BINOP(Float32LessThanOrEqual, Comparison,
|
||||
SignedLessThanOrEqual, Float32)
|
||||
DECL_SINGLE_REP_BINOP(Float64LessThanOrEqual, Comparison,
|
||||
SignedLessThanOrEqual, Float64)
|
||||
|
||||
#undef DECL_SINGLE_REP_BINOP
|
||||
#undef DECL_MULTI_REP_BINOP
|
||||
#undef DECL_SINGLE_REP_BINOP_NO_KIND
|
||||
|
||||
#define DECL_MULTI_REP_UNARY(name, operation, kind) \
|
||||
OpIndex name(OpIndex input, MachineRepresentation rep) { \
|
||||
return subclass().operation(input, operation##Op::Kind::k##kind, rep); \
|
||||
}
|
||||
#define DECL_SINGLE_REP_UNARY(name, operation, kind, rep) \
|
||||
OpIndex name(OpIndex input) { \
|
||||
return subclass().operation(input, operation##Op::Kind::k##kind, \
|
||||
MachineRepresentation::k##rep); \
|
||||
}
|
||||
|
||||
DECL_MULTI_REP_UNARY(FloatAbs, FloatUnary, Abs)
|
||||
DECL_SINGLE_REP_UNARY(Float32Abs, FloatUnary, Abs, Float32)
|
||||
DECL_SINGLE_REP_UNARY(Float64Abs, FloatUnary, Abs, Float64)
|
||||
DECL_MULTI_REP_UNARY(FloatNegate, FloatUnary, Negate)
|
||||
DECL_SINGLE_REP_UNARY(Float32Negate, FloatUnary, Negate, Float32)
|
||||
DECL_SINGLE_REP_UNARY(Float64Negate, FloatUnary, Negate, Float64)
|
||||
DECL_SINGLE_REP_UNARY(Float64SilenceNaN, FloatUnary, SilenceNaN, Float64)
|
||||
DECL_MULTI_REP_UNARY(FloatRoundDown, FloatUnary, RoundDown)
|
||||
DECL_SINGLE_REP_UNARY(Float32RoundDown, FloatUnary, RoundDown, Float32)
|
||||
DECL_SINGLE_REP_UNARY(Float64RoundDown, FloatUnary, RoundDown, Float64)
|
||||
DECL_MULTI_REP_UNARY(FloatRoundUp, FloatUnary, RoundUp)
|
||||
DECL_SINGLE_REP_UNARY(Float32RoundUp, FloatUnary, RoundUp, Float32)
|
||||
DECL_SINGLE_REP_UNARY(Float64RoundUp, FloatUnary, RoundUp, Float64)
|
||||
DECL_MULTI_REP_UNARY(FloatRoundToZero, FloatUnary, RoundToZero)
|
||||
DECL_SINGLE_REP_UNARY(Float32RoundToZero, FloatUnary, RoundToZero, Float32)
|
||||
DECL_SINGLE_REP_UNARY(Float64RoundToZero, FloatUnary, RoundToZero, Float64)
|
||||
DECL_MULTI_REP_UNARY(FloatRoundTiesEven, FloatUnary, RoundTiesEven)
|
||||
DECL_SINGLE_REP_UNARY(Float32RoundTiesEven, FloatUnary, RoundTiesEven,
|
||||
Float32)
|
||||
DECL_SINGLE_REP_UNARY(Float64RoundTiesEven, FloatUnary, RoundTiesEven,
|
||||
Float64)
|
||||
DECL_SINGLE_REP_UNARY(Float64Log, FloatUnary, Log, Float64)
|
||||
DECL_MULTI_REP_UNARY(FloatSqrt, FloatUnary, Sqrt)
|
||||
DECL_SINGLE_REP_UNARY(Float32Sqrt, FloatUnary, Sqrt, Float32)
|
||||
DECL_SINGLE_REP_UNARY(Float64Sqrt, FloatUnary, Sqrt, Float64)
|
||||
DECL_SINGLE_REP_UNARY(Float64Exp, FloatUnary, Exp, Float64)
|
||||
DECL_SINGLE_REP_UNARY(Float64Expm1, FloatUnary, Expm1, Float64)
|
||||
DECL_SINGLE_REP_UNARY(Float64Sin, FloatUnary, Sin, Float64)
|
||||
DECL_SINGLE_REP_UNARY(Float64Cos, FloatUnary, Cos, Float64)
|
||||
DECL_SINGLE_REP_UNARY(Float64Sinh, FloatUnary, Sinh, Float64)
|
||||
DECL_SINGLE_REP_UNARY(Float64Cosh, FloatUnary, Cosh, Float64)
|
||||
DECL_SINGLE_REP_UNARY(Float64Asin, FloatUnary, Asin, Float64)
|
||||
DECL_SINGLE_REP_UNARY(Float64Acos, FloatUnary, Acos, Float64)
|
||||
DECL_SINGLE_REP_UNARY(Float64Asinh, FloatUnary, Asinh, Float64)
|
||||
DECL_SINGLE_REP_UNARY(Float64Acosh, FloatUnary, Acosh, Float64)
|
||||
DECL_SINGLE_REP_UNARY(Float64Tan, FloatUnary, Tan, Float64)
|
||||
DECL_SINGLE_REP_UNARY(Float64Tanh, FloatUnary, Tanh, Float64)
|
||||
|
||||
DECL_MULTI_REP_UNARY(WordReverseBytes, WordUnary, ReverseBytes)
|
||||
DECL_SINGLE_REP_UNARY(Word32ReverseBytes, WordUnary, ReverseBytes, Word32)
|
||||
DECL_SINGLE_REP_UNARY(Word64ReverseBytes, WordUnary, ReverseBytes, Word64)
|
||||
DECL_MULTI_REP_UNARY(WordCountLeadingZeros, WordUnary, CountLeadingZeros)
|
||||
DECL_SINGLE_REP_UNARY(Word32CountLeadingZeros, WordUnary, CountLeadingZeros,
|
||||
Word32)
|
||||
DECL_SINGLE_REP_UNARY(Word64CountLeadingZeros, WordUnary, CountLeadingZeros,
|
||||
Word64)
|
||||
#undef DECL_SINGLE_REP_UNARY
|
||||
#undef DECL_MULTI_REP_UNARY
|
||||
|
||||
OpIndex Word32Constant(uint32_t value) {
|
||||
return subclass().Constant(ConstantOp::Kind::kWord32, uint64_t{value});
|
||||
}
|
||||
OpIndex Word32Constant(int32_t value) {
|
||||
return Word32Constant(static_cast<uint32_t>(value));
|
||||
}
|
||||
OpIndex Word64Constant(uint64_t value) {
|
||||
return subclass().Constant(ConstantOp::Kind::kWord64, value);
|
||||
}
|
||||
OpIndex IntegralConstant(uint64_t value, MachineRepresentation rep) {
|
||||
OpIndex Word64Constant(int64_t value) {
|
||||
return Word64Constant(static_cast<uint64_t>(value));
|
||||
}
|
||||
OpIndex WordConstant(uint64_t value, MachineRepresentation rep) {
|
||||
switch (rep) {
|
||||
case MachineRepresentation::kWord32:
|
||||
DCHECK(value <= MaxUnsignedValue(MachineRepresentation::kWord32));
|
||||
return Word32Constant(static_cast<uint32_t>(value));
|
||||
case MachineRepresentation::kWord64:
|
||||
return Word64Constant(value);
|
||||
@ -171,18 +287,68 @@ class AssemblerInterface : public Superclass {
|
||||
OpIndex Float64Constant(double value) {
|
||||
return subclass().Constant(ConstantOp::Kind::kFloat64, value);
|
||||
}
|
||||
|
||||
OpIndex TrucateWord64ToWord32(OpIndex value) {
|
||||
return subclass().Change(value, ChangeOp::Kind::kIntegerTruncate,
|
||||
MachineRepresentation::kWord64,
|
||||
MachineRepresentation::kWord32);
|
||||
OpIndex FloatConstant(double value, MachineRepresentation rep) {
|
||||
switch (rep) {
|
||||
case MachineRepresentation::kFloat32:
|
||||
return Float32Constant(static_cast<float>(value));
|
||||
case MachineRepresentation::kFloat64:
|
||||
return Float64Constant(value);
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
OpIndex NumberConstant(double value) {
|
||||
return subclass().Constant(ConstantOp::Kind::kNumber, value);
|
||||
}
|
||||
OpIndex TaggedIndexConstant(int32_t value) {
|
||||
return subclass().Constant(ConstantOp::Kind::kTaggedIndex,
|
||||
uint64_t{static_cast<uint32_t>(value)});
|
||||
}
|
||||
OpIndex HeapConstant(Handle<HeapObject> value) {
|
||||
return subclass().Constant(ConstantOp::Kind::kHeapObject, value);
|
||||
}
|
||||
OpIndex CompressedHeapConstant(Handle<HeapObject> value) {
|
||||
return subclass().Constant(ConstantOp::Kind::kHeapObject, value);
|
||||
}
|
||||
OpIndex ExternalConstant(ExternalReference value) {
|
||||
return subclass().Constant(ConstantOp::Kind::kExternal, value);
|
||||
}
|
||||
|
||||
OpIndex ExceptionValueProjection(OpIndex value) {
|
||||
return subclass().Projection(value, ProjectionOp::Kind::kExceptionValue, 0);
|
||||
#define DECL_CHANGE(name, kind, from, to) \
|
||||
OpIndex name(OpIndex input) { \
|
||||
return subclass().Change(input, ChangeOp::Kind::k##kind, \
|
||||
MachineRepresentation::k##from, \
|
||||
MachineRepresentation::k##to); \
|
||||
}
|
||||
OpIndex TupleProjection(OpIndex value, uint16_t index) {
|
||||
return subclass().Projection(value, ProjectionOp::Kind::kTuple, index);
|
||||
|
||||
DECL_CHANGE(BitcastWord32ToWord64, Bitcast, Word32, Word64)
|
||||
DECL_CHANGE(BitcastFloat32ToWord32, Bitcast, Float32, Word32)
|
||||
DECL_CHANGE(BitcastWord32ToFloat32, Bitcast, Word32, Float32)
|
||||
DECL_CHANGE(BitcastFloat64ToWord64, Bitcast, Float64, Word64)
|
||||
DECL_CHANGE(BitcastWord6464ToFloat64, Bitcast, Word64, Float64)
|
||||
DECL_CHANGE(ChangeUint32ToUint64, ZeroExtend, Word32, Word64)
|
||||
DECL_CHANGE(ChangeInt32ToInt64, SignExtend, Word32, Word64)
|
||||
DECL_CHANGE(ChangeInt32ToFloat64, SignedToFloat, Word32, Float64)
|
||||
DECL_CHANGE(ChangeInt64ToFloat64, SignedToFloat, Word64, Float64)
|
||||
DECL_CHANGE(ChangeUint32ToFloat64, UnsignedToFloat, Word32, Float64)
|
||||
DECL_CHANGE(ChangeFloat64ToFloat32, FloatConversion, Float64, Float32)
|
||||
DECL_CHANGE(ChangeFloat32ToFloat64, FloatConversion, Float32, Float64)
|
||||
DECL_CHANGE(JSTruncateFloat64ToWord32, JSFloatTruncate, Float64, Word32)
|
||||
DECL_CHANGE(TruncateFloat64ToInt32OverflowUndefined, SignedFloatTruncate,
|
||||
Float64, Word32)
|
||||
DECL_CHANGE(TruncateFloat64ToInt32OverflowToMin,
|
||||
SignedFloatTruncateOverflowToMin, Float64, Word32)
|
||||
DECL_CHANGE(NarrowFloat64ToInt32, SignedNarrowing, Float64, Word32)
|
||||
DECL_CHANGE(NarrowFloat64ToUint32, UnsignedNarrowing, Float64, Word32)
|
||||
DECL_CHANGE(NarrowFloat64ToInt64, SignedNarrowing, Float64, Word64)
|
||||
DECL_CHANGE(NarrowFloat64ToUint64, UnsignedNarrowing, Float64, Word64)
|
||||
DECL_CHANGE(Float64ExtractLowWord32, ExtractLowHalf, Float64, Word32)
|
||||
DECL_CHANGE(Float64ExtractHighWord32, ExtractHighHalf, Float64, Word32)
|
||||
#undef DECL_CHANGE
|
||||
|
||||
using Base::Tuple;
|
||||
OpIndex Tuple(OpIndex a, OpIndex b) {
|
||||
return subclass().Tuple(base::VectorOf({a, b}));
|
||||
}
|
||||
|
||||
private:
|
||||
@ -263,6 +429,7 @@ class Assembler
|
||||
explicit Assembler(Graph* graph, Zone* phase_zone)
|
||||
: graph_(*graph), phase_zone_(phase_zone) {
|
||||
graph_.Reset();
|
||||
SupportedOperations::Initialize();
|
||||
}
|
||||
|
||||
Block* current_block() { return current_block_; }
|
||||
|
@ -121,8 +121,8 @@ void DecompressionAnalyzer::ProcessOperation(const Operation& op) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Opcode::kBinop: {
|
||||
auto& binary_op = op.Cast<BinopOp>();
|
||||
case Opcode::kWordBinop: {
|
||||
auto& binary_op = op.Cast<WordBinopOp>();
|
||||
if (binary_op.rep == MachineRepresentation::kWord64) {
|
||||
MarkAsNeedsDecompression(binary_op.left());
|
||||
MarkAsNeedsDecompression(binary_op.right());
|
||||
|
@ -209,7 +209,11 @@ base::Optional<BailoutReason> GraphBuilder::Run() {
|
||||
DCHECK_EQ(block->SuccessorCount(), 2);
|
||||
Block* if_success = Map(block->SuccessorAt(0));
|
||||
Block* if_exception = Map(block->SuccessorAt(1));
|
||||
assembler.CatchException(Map(call), if_success, if_exception);
|
||||
OpIndex catch_exception =
|
||||
assembler.CatchException(Map(call), if_success, if_exception);
|
||||
Node* if_exception_node = block->SuccessorAt(1)->NodeAt(0);
|
||||
DCHECK_EQ(if_exception_node->opcode(), IrOpcode::kIfException);
|
||||
op_mapping.Set(if_exception_node, catch_exception);
|
||||
break;
|
||||
}
|
||||
case BasicBlock::kTailCall:
|
||||
@ -264,8 +268,13 @@ OpIndex GraphBuilder::Process(
|
||||
case IrOpcode::kIfSuccess:
|
||||
return OpIndex::Invalid();
|
||||
|
||||
case IrOpcode::kIfException:
|
||||
return assembler.ExceptionValueProjection(Map(node->InputAt(0)));
|
||||
case IrOpcode::kIfException: {
|
||||
// Use the `CatchExceptionOp` that has already been produced when
|
||||
// processing the call.
|
||||
OpIndex catch_exception = Map(node);
|
||||
DCHECK(assembler.graph().Get(catch_exception).Is<CatchExceptionOp>());
|
||||
return catch_exception;
|
||||
}
|
||||
|
||||
case IrOpcode::kParameter: {
|
||||
const ParameterInfo& info = ParameterInfoOf(op);
|
||||
@ -293,56 +302,106 @@ OpIndex GraphBuilder::Process(
|
||||
}
|
||||
|
||||
case IrOpcode::kInt64Constant:
|
||||
return assembler.Constant(
|
||||
ConstantOp::Kind::kWord64,
|
||||
return assembler.Word64Constant(
|
||||
static_cast<uint64_t>(OpParameter<int64_t>(op)));
|
||||
case IrOpcode::kInt32Constant:
|
||||
return assembler.Constant(
|
||||
ConstantOp::Kind::kWord32,
|
||||
uint64_t{static_cast<uint32_t>(OpParameter<int32_t>(op))});
|
||||
return assembler.Word32Constant(
|
||||
static_cast<uint32_t>(OpParameter<int32_t>(op)));
|
||||
case IrOpcode::kFloat64Constant:
|
||||
return assembler.Constant(ConstantOp::Kind::kFloat64,
|
||||
OpParameter<double>(op));
|
||||
return assembler.Float64Constant(OpParameter<double>(op));
|
||||
case IrOpcode::kFloat32Constant:
|
||||
return assembler.Constant(ConstantOp::Kind::kFloat32,
|
||||
OpParameter<float>(op));
|
||||
return assembler.Float32Constant(OpParameter<float>(op));
|
||||
case IrOpcode::kNumberConstant:
|
||||
return assembler.Constant(ConstantOp::Kind::kNumber,
|
||||
OpParameter<double>(op));
|
||||
return assembler.NumberConstant(OpParameter<double>(op));
|
||||
case IrOpcode::kTaggedIndexConstant:
|
||||
return assembler.Constant(
|
||||
ConstantOp::Kind::kTaggedIndex,
|
||||
uint64_t{static_cast<uint32_t>(OpParameter<int32_t>(op))});
|
||||
return assembler.TaggedIndexConstant(OpParameter<int32_t>(op));
|
||||
case IrOpcode::kHeapConstant:
|
||||
return assembler.Constant(ConstantOp::Kind::kHeapObject,
|
||||
HeapConstantOf(op));
|
||||
return assembler.HeapConstant(HeapConstantOf(op));
|
||||
case IrOpcode::kCompressedHeapConstant:
|
||||
return assembler.Constant(ConstantOp::Kind::kCompressedHeapObject,
|
||||
HeapConstantOf(op));
|
||||
return assembler.CompressedHeapConstant(HeapConstantOf(op));
|
||||
case IrOpcode::kExternalConstant:
|
||||
return assembler.Constant(ConstantOp::Kind::kExternal,
|
||||
OpParameter<ExternalReference>(op));
|
||||
return assembler.ExternalConstant(OpParameter<ExternalReference>(op));
|
||||
|
||||
case IrOpcode::kWord32And:
|
||||
return assembler.BitwiseAnd(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kWord64And:
|
||||
return assembler.BitwiseAnd(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord64);
|
||||
#define BINOP_CASE(opcode, assembler_op) \
|
||||
case IrOpcode::k##opcode: \
|
||||
return assembler.assembler_op(Map(node->InputAt(0)), Map(node->InputAt(1)));
|
||||
|
||||
case IrOpcode::kWord32Or:
|
||||
return assembler.BitwiseOr(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kWord64Or:
|
||||
return assembler.BitwiseOr(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord64);
|
||||
BINOP_CASE(Int32Add, Word32Add)
|
||||
BINOP_CASE(Int64Add, Word64Add)
|
||||
BINOP_CASE(Int32Mul, Word32Mul)
|
||||
BINOP_CASE(Int64Mul, Word64Mul)
|
||||
BINOP_CASE(Word32And, Word32BitwiseAnd)
|
||||
BINOP_CASE(Word64And, Word64BitwiseAnd)
|
||||
BINOP_CASE(Word32Or, Word32BitwiseOr)
|
||||
BINOP_CASE(Word64Or, Word64BitwiseOr)
|
||||
BINOP_CASE(Word32Xor, Word32BitwiseXor)
|
||||
BINOP_CASE(Word64Xor, Word64BitwiseXor)
|
||||
BINOP_CASE(Int32Sub, Word32Sub)
|
||||
BINOP_CASE(Int64Sub, Word64Sub)
|
||||
BINOP_CASE(Int32Div, Int32Div)
|
||||
BINOP_CASE(Uint32Div, Uint32Div)
|
||||
BINOP_CASE(Int64Div, Int64Div)
|
||||
BINOP_CASE(Uint64Div, Uint64Div)
|
||||
BINOP_CASE(Int32Mod, Int32Mod)
|
||||
BINOP_CASE(Uint32Mod, Uint32Mod)
|
||||
BINOP_CASE(Int64Mod, Int64Mod)
|
||||
BINOP_CASE(Uint64Mod, Uint64Mod)
|
||||
BINOP_CASE(Int32MulHigh, Int32MulOverflownBits)
|
||||
BINOP_CASE(Uint32MulHigh, Uint32MulOverflownBits)
|
||||
|
||||
case IrOpcode::kWord32Xor:
|
||||
return assembler.BitwiseXor(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kWord64Xor:
|
||||
return assembler.BitwiseXor(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord64);
|
||||
BINOP_CASE(Float32Add, Float32Add)
|
||||
BINOP_CASE(Float64Add, Float64Add)
|
||||
BINOP_CASE(Float32Sub, Float32Sub)
|
||||
BINOP_CASE(Float64Sub, Float64Sub)
|
||||
BINOP_CASE(Float64Mul, Float64Mul)
|
||||
BINOP_CASE(Float32Mul, Float32Mul)
|
||||
BINOP_CASE(Float32Div, Float32Div)
|
||||
BINOP_CASE(Float64Div, Float64Div)
|
||||
BINOP_CASE(Float32Min, Float32Min)
|
||||
BINOP_CASE(Float64Min, Float64Min)
|
||||
BINOP_CASE(Float32Max, Float32Max)
|
||||
BINOP_CASE(Float64Max, Float64Max)
|
||||
BINOP_CASE(Float64Mod, Float64Mod)
|
||||
BINOP_CASE(Float64Pow, Float64Power)
|
||||
BINOP_CASE(Float64Atan2, Float64Atan2)
|
||||
|
||||
BINOP_CASE(Int32AddWithOverflow, Int32AddCheckOverflow)
|
||||
BINOP_CASE(Int64AddWithOverflow, Int64AddCheckOverflow)
|
||||
BINOP_CASE(Int32MulWithOverflow, Int32MulCheckOverflow)
|
||||
BINOP_CASE(Int32SubWithOverflow, Int32SubCheckOverflow)
|
||||
BINOP_CASE(Int64SubWithOverflow, Int64SubCheckOverflow)
|
||||
|
||||
BINOP_CASE(Word32Shr, Word32ShiftRightLogical)
|
||||
BINOP_CASE(Word64Shr, Word64ShiftRightLogical)
|
||||
|
||||
BINOP_CASE(Word32Shl, Word32ShiftLeft)
|
||||
BINOP_CASE(Word64Shl, Word64ShiftLeft)
|
||||
|
||||
BINOP_CASE(Word32Rol, Word32RotateLeft)
|
||||
BINOP_CASE(Word64Rol, Word64RotateLeft)
|
||||
|
||||
BINOP_CASE(Word32Ror, Word32RotateRight)
|
||||
BINOP_CASE(Word64Ror, Word64RotateRight)
|
||||
|
||||
BINOP_CASE(Word32Equal, Word32Equal)
|
||||
BINOP_CASE(Word64Equal, Word64Equal)
|
||||
BINOP_CASE(Float32Equal, Float32Equal)
|
||||
BINOP_CASE(Float64Equal, Float64Equal)
|
||||
|
||||
BINOP_CASE(Int32LessThan, Int32LessThan)
|
||||
BINOP_CASE(Int64LessThan, Int64LessThan)
|
||||
BINOP_CASE(Uint32LessThan, Uint32LessThan)
|
||||
BINOP_CASE(Uint64LessThan, Uint64LessThan)
|
||||
BINOP_CASE(Float32LessThan, Float32LessThan)
|
||||
BINOP_CASE(Float64LessThan, Float64LessThan)
|
||||
|
||||
BINOP_CASE(Int32LessThanOrEqual, Int32LessThanOrEqual)
|
||||
BINOP_CASE(Int64LessThanOrEqual, Int64LessThanOrEqual)
|
||||
BINOP_CASE(Uint32LessThanOrEqual, Uint32LessThanOrEqual)
|
||||
BINOP_CASE(Uint64LessThanOrEqual, Uint64LessThanOrEqual)
|
||||
BINOP_CASE(Float32LessThanOrEqual, Float32LessThanOrEqual)
|
||||
BINOP_CASE(Float64LessThanOrEqual, Float64LessThanOrEqual)
|
||||
#undef BINOP_CASE
|
||||
|
||||
case IrOpcode::kWord64Sar:
|
||||
case IrOpcode::kWord32Sar: {
|
||||
@ -362,401 +421,75 @@ OpIndex GraphBuilder::Process(
|
||||
rep);
|
||||
}
|
||||
|
||||
case IrOpcode::kWord32Shr:
|
||||
return assembler.ShiftRightLogical(Map(node->InputAt(0)),
|
||||
Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kWord64Shr:
|
||||
return assembler.ShiftRightLogical(Map(node->InputAt(0)),
|
||||
Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord64);
|
||||
#define UNARY_CASE(opcode, assembler_op) \
|
||||
case IrOpcode::k##opcode: \
|
||||
return assembler.assembler_op(Map(node->InputAt(0)));
|
||||
|
||||
case IrOpcode::kWord32Shl:
|
||||
return assembler.ShiftLeft(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kWord64Shl:
|
||||
return assembler.ShiftLeft(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord64);
|
||||
UNARY_CASE(Word32ReverseBytes, Word32ReverseBytes)
|
||||
UNARY_CASE(Word64ReverseBytes, Word64ReverseBytes)
|
||||
UNARY_CASE(Word32Clz, Word32CountLeadingZeros)
|
||||
UNARY_CASE(Word64Clz, Word64CountLeadingZeros)
|
||||
|
||||
case IrOpcode::kWord32Rol:
|
||||
return assembler.RotateLeft(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kWord64Rol:
|
||||
return assembler.RotateLeft(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord64);
|
||||
UNARY_CASE(Float32Abs, Float32Abs)
|
||||
UNARY_CASE(Float64Abs, Float64Abs)
|
||||
UNARY_CASE(Float32Neg, Float32Negate)
|
||||
UNARY_CASE(Float64Neg, Float64Negate)
|
||||
UNARY_CASE(Float64SilenceNaN, Float64SilenceNaN)
|
||||
UNARY_CASE(Float32RoundDown, Float32RoundDown)
|
||||
UNARY_CASE(Float64RoundDown, Float64RoundDown)
|
||||
UNARY_CASE(Float32RoundUp, Float32RoundUp)
|
||||
UNARY_CASE(Float64RoundUp, Float64RoundUp)
|
||||
UNARY_CASE(Float32RoundTruncate, Float32RoundToZero)
|
||||
UNARY_CASE(Float64RoundTruncate, Float64RoundToZero)
|
||||
UNARY_CASE(Float32RoundTiesEven, Float32RoundTiesEven)
|
||||
UNARY_CASE(Float64RoundTiesEven, Float64RoundTiesEven)
|
||||
UNARY_CASE(Float64Log, Float64Log)
|
||||
UNARY_CASE(Float32Sqrt, Float32Sqrt)
|
||||
UNARY_CASE(Float64Sqrt, Float64Sqrt)
|
||||
UNARY_CASE(Float64Exp, Float64Exp)
|
||||
UNARY_CASE(Float64Expm1, Float64Expm1)
|
||||
UNARY_CASE(Float64Sin, Float64Sin)
|
||||
UNARY_CASE(Float64Cos, Float64Cos)
|
||||
UNARY_CASE(Float64Sinh, Float64Sinh)
|
||||
UNARY_CASE(Float64Cosh, Float64Cosh)
|
||||
UNARY_CASE(Float64Asin, Float64Asin)
|
||||
UNARY_CASE(Float64Acos, Float64Acos)
|
||||
UNARY_CASE(Float64Asinh, Float64Asinh)
|
||||
UNARY_CASE(Float64Acosh, Float64Acosh)
|
||||
UNARY_CASE(Float64Tan, Float64Tan)
|
||||
UNARY_CASE(Float64Tanh, Float64Tanh)
|
||||
#undef UNARY_CASE
|
||||
|
||||
case IrOpcode::kWord32Ror:
|
||||
return assembler.RotateRight(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kWord64Ror:
|
||||
return assembler.RotateRight(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord64);
|
||||
|
||||
case IrOpcode::kWord32Equal:
|
||||
return assembler.Equal(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kWord64Equal:
|
||||
return assembler.Equal(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord64);
|
||||
case IrOpcode::kFloat32Equal:
|
||||
return assembler.Equal(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kFloat32);
|
||||
case IrOpcode::kFloat64Equal:
|
||||
return assembler.Equal(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kFloat64);
|
||||
|
||||
case IrOpcode::kInt32LessThan:
|
||||
return assembler.Comparison(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
ComparisonOp::Kind::kSignedLessThan,
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kInt64LessThan:
|
||||
return assembler.Comparison(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
ComparisonOp::Kind::kSignedLessThan,
|
||||
MachineRepresentation::kWord64);
|
||||
case IrOpcode::kUint32LessThan:
|
||||
return assembler.Comparison(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
ComparisonOp::Kind::kUnsignedLessThan,
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kUint64LessThan:
|
||||
return assembler.Comparison(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
ComparisonOp::Kind::kUnsignedLessThan,
|
||||
MachineRepresentation::kWord64);
|
||||
case IrOpcode::kFloat32LessThan:
|
||||
return assembler.Comparison(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
ComparisonOp::Kind::kSignedLessThan,
|
||||
MachineRepresentation::kFloat32);
|
||||
case IrOpcode::kFloat64LessThan:
|
||||
return assembler.Comparison(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
ComparisonOp::Kind::kSignedLessThan,
|
||||
MachineRepresentation::kFloat64);
|
||||
|
||||
case IrOpcode::kInt32LessThanOrEqual:
|
||||
return assembler.Comparison(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
ComparisonOp::Kind::kSignedLessThanOrEqual,
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kInt64LessThanOrEqual:
|
||||
return assembler.Comparison(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
ComparisonOp::Kind::kSignedLessThanOrEqual,
|
||||
MachineRepresentation::kWord64);
|
||||
case IrOpcode::kUint32LessThanOrEqual:
|
||||
return assembler.Comparison(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
ComparisonOp::Kind::kUnsignedLessThanOrEqual,
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kUint64LessThanOrEqual:
|
||||
return assembler.Comparison(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
ComparisonOp::Kind::kUnsignedLessThanOrEqual,
|
||||
MachineRepresentation::kWord64);
|
||||
case IrOpcode::kFloat32LessThanOrEqual:
|
||||
return assembler.Comparison(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
ComparisonOp::Kind::kSignedLessThanOrEqual,
|
||||
MachineRepresentation::kFloat32);
|
||||
case IrOpcode::kFloat64LessThanOrEqual:
|
||||
return assembler.Comparison(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
ComparisonOp::Kind::kSignedLessThanOrEqual,
|
||||
MachineRepresentation::kFloat64);
|
||||
|
||||
case IrOpcode::kInt32Add:
|
||||
return assembler.Add(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kInt32AddWithOverflow:
|
||||
return assembler.AddWithOverflow(Map(node->InputAt(0)),
|
||||
Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kInt64Add:
|
||||
return assembler.Add(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord64);
|
||||
case IrOpcode::kInt64AddWithOverflow:
|
||||
return assembler.AddWithOverflow(Map(node->InputAt(0)),
|
||||
Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord64);
|
||||
case IrOpcode::kFloat64Add:
|
||||
return assembler.Add(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kFloat32Add:
|
||||
return assembler.Add(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kFloat32);
|
||||
|
||||
case IrOpcode::kInt32Mul:
|
||||
return assembler.Mul(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kInt32MulHigh:
|
||||
return assembler.SignedMulOverflownBits(Map(node->InputAt(0)),
|
||||
Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kUint32MulHigh:
|
||||
return assembler.UnsignedMulOverflownBits(Map(node->InputAt(0)),
|
||||
Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kInt32MulWithOverflow:
|
||||
return assembler.MulWithOverflow(Map(node->InputAt(0)),
|
||||
Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kInt64Mul:
|
||||
return assembler.Mul(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord64);
|
||||
case IrOpcode::kFloat64Mul:
|
||||
return assembler.Mul(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kFloat32Mul:
|
||||
return assembler.Mul(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kFloat32);
|
||||
|
||||
case IrOpcode::kInt32Div:
|
||||
return assembler.SignedDiv(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kUint32Div:
|
||||
return assembler.UnsignedDiv(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kInt64Div:
|
||||
return assembler.SignedDiv(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord64);
|
||||
case IrOpcode::kUint64Div:
|
||||
return assembler.UnsignedDiv(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord64);
|
||||
case IrOpcode::kFloat32Div:
|
||||
return assembler.SignedDiv(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kFloat32);
|
||||
case IrOpcode::kFloat64Div:
|
||||
return assembler.SignedDiv(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kFloat64);
|
||||
|
||||
case IrOpcode::kInt32Mod:
|
||||
return assembler.SignedMod(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kUint32Mod:
|
||||
return assembler.UnsignedMod(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kInt64Mod:
|
||||
return assembler.SignedMod(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord64);
|
||||
case IrOpcode::kUint64Mod:
|
||||
return assembler.UnsignedMod(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord64);
|
||||
case IrOpcode::kFloat64Mod:
|
||||
return assembler.SignedMod(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kFloat64);
|
||||
|
||||
case IrOpcode::kInt32Sub:
|
||||
return assembler.Sub(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kInt32SubWithOverflow:
|
||||
return assembler.SubWithOverflow(Map(node->InputAt(0)),
|
||||
Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kInt64Sub:
|
||||
return assembler.Sub(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord64);
|
||||
case IrOpcode::kInt64SubWithOverflow:
|
||||
return assembler.SubWithOverflow(Map(node->InputAt(0)),
|
||||
Map(node->InputAt(1)),
|
||||
MachineRepresentation::kWord64);
|
||||
case IrOpcode::kFloat64Sub:
|
||||
return assembler.Sub(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kFloat32Sub:
|
||||
return assembler.Sub(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kFloat32);
|
||||
|
||||
case IrOpcode::kFloat64Min:
|
||||
return assembler.Min(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kFloat32Min:
|
||||
return assembler.Min(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kFloat32);
|
||||
case IrOpcode::kFloat64Max:
|
||||
return assembler.Max(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kFloat32Max:
|
||||
return assembler.Max(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kFloat32);
|
||||
|
||||
case IrOpcode::kFloat64Pow:
|
||||
return assembler.Power(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kFloat64Atan2:
|
||||
return assembler.Atan2(Map(node->InputAt(0)), Map(node->InputAt(1)),
|
||||
MachineRepresentation::kFloat64);
|
||||
|
||||
case IrOpcode::kWord32ReverseBytes:
|
||||
return assembler.IntegerUnary(Map(node->InputAt(0)),
|
||||
IntegerUnaryOp::Kind::kReverseBytes,
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kWord64ReverseBytes:
|
||||
return assembler.IntegerUnary(Map(node->InputAt(0)),
|
||||
IntegerUnaryOp::Kind::kReverseBytes,
|
||||
MachineRepresentation::kWord64);
|
||||
case IrOpcode::kWord32Clz:
|
||||
return assembler.IntegerUnary(Map(node->InputAt(0)),
|
||||
IntegerUnaryOp::Kind::kCountLeadingZeros,
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kWord64Clz:
|
||||
return assembler.IntegerUnary(Map(node->InputAt(0)),
|
||||
IntegerUnaryOp::Kind::kCountLeadingZeros,
|
||||
MachineRepresentation::kWord64);
|
||||
|
||||
case IrOpcode::kFloat32Abs:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kAbs,
|
||||
MachineRepresentation::kFloat32);
|
||||
case IrOpcode::kFloat64Abs:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kAbs,
|
||||
MachineRepresentation::kFloat64);
|
||||
|
||||
case IrOpcode::kFloat32Neg:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kNegate,
|
||||
MachineRepresentation::kFloat32);
|
||||
case IrOpcode::kFloat64Neg:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kNegate,
|
||||
MachineRepresentation::kFloat64);
|
||||
|
||||
case IrOpcode::kFloat64SilenceNaN:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kSilenceNaN,
|
||||
MachineRepresentation::kFloat64);
|
||||
|
||||
case IrOpcode::kFloat32RoundDown:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kRoundDown,
|
||||
MachineRepresentation::kFloat32);
|
||||
case IrOpcode::kFloat64RoundDown:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kRoundDown,
|
||||
MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kFloat32RoundUp:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kRoundUp,
|
||||
MachineRepresentation::kFloat32);
|
||||
case IrOpcode::kFloat64RoundUp:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kRoundUp,
|
||||
MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kFloat32RoundTruncate:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kRoundToZero,
|
||||
MachineRepresentation::kFloat32);
|
||||
case IrOpcode::kFloat64RoundTruncate:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kRoundToZero,
|
||||
MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kFloat32RoundTiesEven:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kRoundTiesEven,
|
||||
MachineRepresentation::kFloat32);
|
||||
case IrOpcode::kFloat64RoundTiesEven:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kRoundTiesEven,
|
||||
MachineRepresentation::kFloat64);
|
||||
|
||||
case IrOpcode::kFloat64Log:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kLog,
|
||||
MachineRepresentation::kFloat64);
|
||||
|
||||
case IrOpcode::kFloat32Sqrt:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kSqrt,
|
||||
MachineRepresentation::kFloat32);
|
||||
case IrOpcode::kFloat64Sqrt:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kSqrt,
|
||||
MachineRepresentation::kFloat64);
|
||||
|
||||
case IrOpcode::kFloat64Exp:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kExp,
|
||||
MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kFloat64Expm1:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kExpm1,
|
||||
MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kFloat64Sin:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kSin,
|
||||
MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kFloat64Cos:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kCos,
|
||||
MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kFloat64Sinh:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kSinh,
|
||||
MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kFloat64Cosh:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kCosh,
|
||||
MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kFloat64Asin:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kAsin,
|
||||
MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kFloat64Acos:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kAcos,
|
||||
MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kFloat64Asinh:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kAsinh,
|
||||
MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kFloat64Acosh:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kAcosh,
|
||||
MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kFloat64Tan:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kTan,
|
||||
MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kFloat64Tanh:
|
||||
return assembler.FloatUnary(Map(node->InputAt(0)),
|
||||
FloatUnaryOp::Kind::kTanh,
|
||||
MachineRepresentation::kFloat64);
|
||||
#define CHANGE_CASE(opcode, kind, from, to) \
|
||||
case IrOpcode::k##opcode: \
|
||||
return assembler.Change(Map(node->InputAt(0)), ChangeOp::Kind::k##kind, \
|
||||
MachineRepresentation::k##from, \
|
||||
MachineRepresentation::k##to);
|
||||
|
||||
CHANGE_CASE(BitcastWord32ToWord64, Bitcast, Word32, Word64)
|
||||
CHANGE_CASE(BitcastFloat32ToInt32, Bitcast, Float32, Word32)
|
||||
CHANGE_CASE(BitcastInt32ToFloat32, Bitcast, Word32, Float32)
|
||||
CHANGE_CASE(BitcastFloat64ToInt64, Bitcast, Float64, Word64)
|
||||
CHANGE_CASE(BitcastInt64ToFloat64, Bitcast, Word64, Float64)
|
||||
CHANGE_CASE(ChangeUint32ToUint64, ZeroExtend, Word32, Word64)
|
||||
CHANGE_CASE(ChangeInt32ToInt64, SignExtend, Word32, Word64)
|
||||
CHANGE_CASE(ChangeInt32ToFloat64, SignedToFloat, Word32, Float64)
|
||||
CHANGE_CASE(ChangeInt64ToFloat64, SignedToFloat, Word64, Float64)
|
||||
CHANGE_CASE(ChangeUint32ToFloat64, UnsignedToFloat, Word32, Float64)
|
||||
CHANGE_CASE(TruncateFloat64ToWord32, JSFloatTruncate, Float64, Word32)
|
||||
CHANGE_CASE(TruncateFloat64ToFloat32, FloatConversion, Float64, Float32)
|
||||
CHANGE_CASE(ChangeFloat32ToFloat64, FloatConversion, Float32, Float64)
|
||||
CHANGE_CASE(RoundFloat64ToInt32, SignedFloatTruncate, Float64, Word32)
|
||||
CHANGE_CASE(ChangeFloat64ToInt32, SignedNarrowing, Float64, Word32)
|
||||
CHANGE_CASE(ChangeFloat64ToUint32, UnsignedNarrowing, Float64, Word32)
|
||||
CHANGE_CASE(ChangeFloat64ToInt64, SignedNarrowing, Float64, Word64)
|
||||
CHANGE_CASE(ChangeFloat64ToUint64, UnsignedNarrowing, Float64, Word64)
|
||||
CHANGE_CASE(Float64ExtractLowWord32, ExtractLowHalf, Float64, Word32)
|
||||
CHANGE_CASE(Float64ExtractHighWord32, ExtractHighHalf, Float64, Word32)
|
||||
#undef CHANGE_CASE
|
||||
case IrOpcode::kTruncateInt64ToInt32:
|
||||
return assembler.Change(
|
||||
Map(node->InputAt(0)), ChangeOp::Kind::kIntegerTruncate,
|
||||
MachineRepresentation::kWord64, MachineRepresentation::kWord32);
|
||||
case IrOpcode::kBitcastWord32ToWord64:
|
||||
return assembler.Change(Map(node->InputAt(0)), ChangeOp::Kind::kBitcast,
|
||||
MachineRepresentation::kWord32,
|
||||
MachineRepresentation::kWord64);
|
||||
case IrOpcode::kBitcastFloat32ToInt32:
|
||||
return assembler.Change(Map(node->InputAt(0)), ChangeOp::Kind::kBitcast,
|
||||
MachineRepresentation::kFloat32,
|
||||
MachineRepresentation::kWord32);
|
||||
case IrOpcode::kBitcastInt32ToFloat32:
|
||||
return assembler.Change(Map(node->InputAt(0)), ChangeOp::Kind::kBitcast,
|
||||
MachineRepresentation::kWord32,
|
||||
MachineRepresentation::kFloat32);
|
||||
case IrOpcode::kBitcastFloat64ToInt64:
|
||||
return assembler.Change(Map(node->InputAt(0)), ChangeOp::Kind::kBitcast,
|
||||
MachineRepresentation::kFloat64,
|
||||
MachineRepresentation::kWord64);
|
||||
case IrOpcode::kBitcastInt64ToFloat64:
|
||||
return assembler.Change(Map(node->InputAt(0)), ChangeOp::Kind::kBitcast,
|
||||
MachineRepresentation::kWord64,
|
||||
MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kChangeUint32ToUint64:
|
||||
return assembler.Change(
|
||||
Map(node->InputAt(0)), ChangeOp::Kind::kZeroExtend,
|
||||
MachineRepresentation::kWord32, MachineRepresentation::kWord64);
|
||||
case IrOpcode::kChangeInt32ToInt64:
|
||||
return assembler.Change(
|
||||
Map(node->InputAt(0)), ChangeOp::Kind::kSignExtend,
|
||||
MachineRepresentation::kWord32, MachineRepresentation::kWord64);
|
||||
case IrOpcode::kChangeInt32ToFloat64:
|
||||
return assembler.Change(
|
||||
Map(node->InputAt(0)), ChangeOp::Kind::kSignedToFloat,
|
||||
MachineRepresentation::kWord32, MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kChangeInt64ToFloat64:
|
||||
return assembler.Change(
|
||||
Map(node->InputAt(0)), ChangeOp::Kind::kSignedToFloat,
|
||||
MachineRepresentation::kWord64, MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kChangeUint32ToFloat64:
|
||||
return assembler.Change(
|
||||
Map(node->InputAt(0)), ChangeOp::Kind::kUnsignedToFloat,
|
||||
MachineRepresentation::kWord32, MachineRepresentation::kFloat64);
|
||||
// 64- to 32-bit truncation is implicit in Turboshaft.
|
||||
return Map(node->InputAt(0));
|
||||
case IrOpcode::kTruncateFloat64ToInt64: {
|
||||
ChangeOp::Kind kind;
|
||||
switch (OpParameter<TruncateKind>(op)) {
|
||||
@ -771,46 +504,6 @@ OpIndex GraphBuilder::Process(
|
||||
MachineRepresentation::kFloat64,
|
||||
MachineRepresentation::kWord64);
|
||||
}
|
||||
case IrOpcode::kTruncateFloat64ToWord32:
|
||||
return assembler.Change(
|
||||
Map(node->InputAt(0)), ChangeOp::Kind::kUnsignedFloatTruncate,
|
||||
MachineRepresentation::kFloat64, MachineRepresentation::kWord32);
|
||||
case IrOpcode::kTruncateFloat64ToFloat32:
|
||||
return assembler.Change(
|
||||
Map(node->InputAt(0)), ChangeOp::Kind::kFloatConversion,
|
||||
MachineRepresentation::kFloat64, MachineRepresentation::kFloat32);
|
||||
case IrOpcode::kChangeFloat32ToFloat64:
|
||||
return assembler.Change(
|
||||
Map(node->InputAt(0)), ChangeOp::Kind::kFloatConversion,
|
||||
MachineRepresentation::kFloat32, MachineRepresentation::kFloat64);
|
||||
case IrOpcode::kRoundFloat64ToInt32:
|
||||
return assembler.Change(
|
||||
Map(node->InputAt(0)), ChangeOp::Kind::kSignedFloatTruncate,
|
||||
MachineRepresentation::kFloat64, MachineRepresentation::kWord32);
|
||||
case IrOpcode::kChangeFloat64ToInt32:
|
||||
return assembler.Change(
|
||||
Map(node->InputAt(0)), ChangeOp::Kind::kSignedNarrowing,
|
||||
MachineRepresentation::kFloat64, MachineRepresentation::kWord32);
|
||||
case IrOpcode::kChangeFloat64ToUint32:
|
||||
return assembler.Change(
|
||||
Map(node->InputAt(0)), ChangeOp::Kind::kUnsignedNarrowing,
|
||||
MachineRepresentation::kFloat64, MachineRepresentation::kWord32);
|
||||
case IrOpcode::kChangeFloat64ToInt64:
|
||||
return assembler.Change(
|
||||
Map(node->InputAt(0)), ChangeOp::Kind::kSignedNarrowing,
|
||||
MachineRepresentation::kFloat64, MachineRepresentation::kWord64);
|
||||
case IrOpcode::kChangeFloat64ToUint64:
|
||||
return assembler.Change(
|
||||
Map(node->InputAt(0)), ChangeOp::Kind::kUnsignedNarrowing,
|
||||
MachineRepresentation::kFloat64, MachineRepresentation::kWord64);
|
||||
case IrOpcode::kFloat64ExtractLowWord32:
|
||||
return assembler.Change(
|
||||
Map(node->InputAt(0)), ChangeOp::Kind::kExtractLowHalf,
|
||||
MachineRepresentation::kFloat64, MachineRepresentation::kWord32);
|
||||
case IrOpcode::kFloat64ExtractHighWord32:
|
||||
return assembler.Change(
|
||||
Map(node->InputAt(0)), ChangeOp::Kind::kExtractHighHalf,
|
||||
MachineRepresentation::kFloat64, MachineRepresentation::kWord32);
|
||||
|
||||
case IrOpcode::kFloat64InsertLowWord32:
|
||||
return assembler.Float64InsertWord32(
|
||||
@ -990,8 +683,7 @@ OpIndex GraphBuilder::Process(
|
||||
case IrOpcode::kProjection: {
|
||||
Node* input = node->InputAt(0);
|
||||
size_t index = ProjectionIndexOf(op);
|
||||
return assembler.Projection(Map(input), ProjectionOp::Kind::kTuple,
|
||||
index);
|
||||
return assembler.Projection(Map(input), index);
|
||||
}
|
||||
|
||||
default:
|
||||
|
@ -7,10 +7,14 @@
|
||||
#include <atomic>
|
||||
#include <sstream>
|
||||
|
||||
#include "src/base/platform/mutex.h"
|
||||
#include "src/base/platform/platform.h"
|
||||
#include "src/codegen/machine-type.h"
|
||||
#include "src/common/assert-scope.h"
|
||||
#include "src/common/globals.h"
|
||||
#include "src/compiler/backend/instruction-selector.h"
|
||||
#include "src/compiler/frame-states.h"
|
||||
#include "src/compiler/machine-operator.h"
|
||||
#include "src/compiler/turboshaft/deopt-data.h"
|
||||
#include "src/compiler/turboshaft/graph.h"
|
||||
#include "src/handles/handles-inl.h"
|
||||
@ -39,11 +43,11 @@ std::ostream& operator<<(std::ostream& os, OperationPrintStyle styled_op) {
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, IntegerUnaryOp::Kind kind) {
|
||||
std::ostream& operator<<(std::ostream& os, WordUnaryOp::Kind kind) {
|
||||
switch (kind) {
|
||||
case IntegerUnaryOp::Kind::kReverseBytes:
|
||||
case WordUnaryOp::Kind::kReverseBytes:
|
||||
return os << "ReverseBytes";
|
||||
case IntegerUnaryOp::Kind::kCountLeadingZeros:
|
||||
case WordUnaryOp::Kind::kCountLeadingZeros:
|
||||
return os << "CountLeadingZeros";
|
||||
}
|
||||
}
|
||||
@ -95,6 +99,30 @@ std::ostream& operator<<(std::ostream& os, FloatUnaryOp::Kind kind) {
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
bool FloatUnaryOp::IsSupported(Kind kind, MachineRepresentation rep) {
|
||||
switch (kind) {
|
||||
case Kind::kRoundDown:
|
||||
return rep == MachineRepresentation::kFloat32
|
||||
? SupportedOperations::float32_round_down()
|
||||
: SupportedOperations::float64_round_down();
|
||||
case Kind::kRoundUp:
|
||||
return rep == MachineRepresentation::kFloat32
|
||||
? SupportedOperations::float32_round_up()
|
||||
: SupportedOperations::float64_round_up();
|
||||
case Kind::kRoundToZero:
|
||||
return rep == MachineRepresentation::kFloat32
|
||||
? SupportedOperations::float32_round_to_zero()
|
||||
: SupportedOperations::float64_round_to_zero();
|
||||
case Kind::kRoundTiesEven:
|
||||
return rep == MachineRepresentation::kFloat32
|
||||
? SupportedOperations::float32_round_ties_even()
|
||||
: SupportedOperations::float64_round_ties_even();
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, ShiftOp::Kind kind) {
|
||||
switch (kind) {
|
||||
case ShiftOp::Kind::kShiftRightArithmeticShiftOutZeros:
|
||||
@ -131,14 +159,12 @@ std::ostream& operator<<(std::ostream& os, ChangeOp::Kind kind) {
|
||||
return os << "SignedNarrowing";
|
||||
case ChangeOp::Kind::kUnsignedNarrowing:
|
||||
return os << "UnsignedNarrowing";
|
||||
case ChangeOp::Kind::kIntegerTruncate:
|
||||
return os << "IntegerTruncate";
|
||||
case ChangeOp::Kind::kFloatConversion:
|
||||
return os << "FloatConversion";
|
||||
case ChangeOp::Kind::kSignedFloatTruncate:
|
||||
return os << "SignedFloatTruncate";
|
||||
case ChangeOp::Kind::kUnsignedFloatTruncate:
|
||||
return os << "UnsignedFloatTruncate";
|
||||
case ChangeOp::Kind::kJSFloatTruncate:
|
||||
return os << "JSFloatTruncate";
|
||||
case ChangeOp::Kind::kSignedFloatTruncateOverflowToMin:
|
||||
return os << "SignedFloatTruncateOverflowToMin";
|
||||
case ChangeOp::Kind::kSignedToFloat:
|
||||
@ -167,15 +193,6 @@ std::ostream& operator<<(std::ostream& os, Float64InsertWord32Op::Kind kind) {
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, ProjectionOp::Kind kind) {
|
||||
switch (kind) {
|
||||
case ProjectionOp::Kind::kTuple:
|
||||
return os << "tuple";
|
||||
case ProjectionOp::Kind::kExceptionValue:
|
||||
return os << "exception value";
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, FrameConstantOp::Kind kind) {
|
||||
switch (kind) {
|
||||
case FrameConstantOp::Kind::kStackCheckOffset:
|
||||
@ -334,7 +351,7 @@ void FrameStateOp::PrintOptions(std::ostream& os) const {
|
||||
os << "]";
|
||||
}
|
||||
|
||||
void BinopOp::PrintOptions(std::ostream& os) const {
|
||||
void WordBinopOp::PrintOptions(std::ostream& os) const {
|
||||
os << "[";
|
||||
switch (kind) {
|
||||
case Kind::kAdd:
|
||||
@ -373,6 +390,29 @@ void BinopOp::PrintOptions(std::ostream& os) const {
|
||||
case Kind::kBitwiseXor:
|
||||
os << "BitwiseXor, ";
|
||||
break;
|
||||
}
|
||||
os << rep;
|
||||
os << "]";
|
||||
}
|
||||
|
||||
void FloatBinopOp::PrintOptions(std::ostream& os) const {
|
||||
os << "[";
|
||||
switch (kind) {
|
||||
case Kind::kAdd:
|
||||
os << "Add, ";
|
||||
break;
|
||||
case Kind::kSub:
|
||||
os << "Sub, ";
|
||||
break;
|
||||
case Kind::kMul:
|
||||
os << "Mul, ";
|
||||
break;
|
||||
case Kind::kDiv:
|
||||
os << "Div, ";
|
||||
break;
|
||||
case Kind::kMod:
|
||||
os << "Mod, ";
|
||||
break;
|
||||
case Kind::kMin:
|
||||
os << "Min, ";
|
||||
break;
|
||||
@ -419,7 +459,7 @@ std::ostream& operator<<(std::ostream& os, const Block* b) {
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, OpProperties opProperties) {
|
||||
if(opProperties == OpProperties::Pure()) {
|
||||
if (opProperties == OpProperties::Pure()) {
|
||||
os << "Pure";
|
||||
} else if (opProperties == OpProperties::Reading()) {
|
||||
os << "Reading";
|
||||
@ -451,4 +491,22 @@ std::string Operation::ToString() const {
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
base::LazyMutex SupportedOperations::mutex_;
|
||||
SupportedOperations SupportedOperations::instance_;
|
||||
bool SupportedOperations::initialized_;
|
||||
|
||||
void SupportedOperations::Initialize() {
|
||||
base::MutexGuard lock(mutex_.Pointer());
|
||||
if (initialized_) return;
|
||||
initialized_ = true;
|
||||
|
||||
MachineOperatorBuilder::Flags supported =
|
||||
InstructionSelector::SupportedMachineOperatorFlags();
|
||||
#define SET_SUPPORTED(name, machine_name) \
|
||||
instance_.name##_ = supported & MachineOperatorBuilder::Flag::k##machine_name;
|
||||
|
||||
SUPPORTED_OPERATIONS_LIST(SET_SUPPORTED)
|
||||
#undef SET_SUPPORTED
|
||||
}
|
||||
|
||||
} // namespace v8::internal::compiler::turboshaft
|
||||
|
@ -16,12 +16,15 @@
|
||||
#include "src/base/functional.h"
|
||||
#include "src/base/logging.h"
|
||||
#include "src/base/macros.h"
|
||||
#include "src/base/platform/mutex.h"
|
||||
#include "src/base/small-vector.h"
|
||||
#include "src/base/template-utils.h"
|
||||
#include "src/base/vector.h"
|
||||
#include "src/codegen/external-reference.h"
|
||||
#include "src/codegen/machine-type.h"
|
||||
#include "src/common/globals.h"
|
||||
#include "src/compiler/globals.h"
|
||||
#include "src/compiler/turboshaft/utils.h"
|
||||
#include "src/compiler/write-barrier-kind.h"
|
||||
#include "src/zone/zone.h"
|
||||
|
||||
@ -59,9 +62,10 @@ class Graph;
|
||||
// the static `New` function, see `CallOp` for an example.
|
||||
|
||||
#define TURBOSHAFT_OPERATION_LIST(V) \
|
||||
V(Binop) \
|
||||
V(WordBinop) \
|
||||
V(FloatBinop) \
|
||||
V(OverflowCheckedBinop) \
|
||||
V(IntegerUnary) \
|
||||
V(WordUnary) \
|
||||
V(FloatUnary) \
|
||||
V(Shift) \
|
||||
V(Equal) \
|
||||
@ -93,6 +97,7 @@ class Graph;
|
||||
V(Branch) \
|
||||
V(CatchException) \
|
||||
V(Switch) \
|
||||
V(Tuple) \
|
||||
V(Projection)
|
||||
|
||||
enum class Opcode : uint8_t {
|
||||
@ -249,8 +254,7 @@ struct OpProperties {
|
||||
return {false, false, false, true};
|
||||
}
|
||||
bool operator==(const OpProperties& other) const {
|
||||
return can_read == other.can_read &&
|
||||
can_write == other.can_write &&
|
||||
return can_read == other.can_read && can_write == other.can_write &&
|
||||
can_abort == other.can_abort &&
|
||||
is_block_terminator == other.is_block_terminator;
|
||||
}
|
||||
@ -470,7 +474,64 @@ struct FixedArityOperationT : OperationT<Derived> {
|
||||
}
|
||||
};
|
||||
|
||||
struct BinopOp : FixedArityOperationT<2, BinopOp> {
|
||||
#define SUPPORTED_OPERATIONS_LIST(V) \
|
||||
V(float32_round_down, Float32RoundDown) \
|
||||
V(float64_round_down, Float64RoundDown) \
|
||||
V(float32_round_up, Float32RoundUp) \
|
||||
V(float64_round_up, Float64RoundUp) \
|
||||
V(float32_round_to_zero, Float32RoundTruncate) \
|
||||
V(float64_round_to_zero, Float64RoundTruncate) \
|
||||
V(float32_round_ties_even, Float32RoundTiesEven) \
|
||||
V(float64_round_ties_even, Float64RoundTiesEven) \
|
||||
V(float64_round_ties_away, Float64RoundTiesAway) \
|
||||
V(int32_div_is_safe, Int32DivIsSafe) \
|
||||
V(uint32_div_is_safe, Uint32DivIsSafe) \
|
||||
V(word32_shift_is_safe, Word32ShiftIsSafe) \
|
||||
V(word32_ctz, Word32Ctz) \
|
||||
V(word64_ctz, Word64Ctz) \
|
||||
V(word64_ctz_lowerable, Word64CtzLowerable) \
|
||||
V(word32_popcnt, Word32Popcnt) \
|
||||
V(word64_popcnt, Word64Popcnt) \
|
||||
V(word32_reverse_bits, Word32ReverseBits) \
|
||||
V(word64_reverse_bits, Word64ReverseBits) \
|
||||
V(float32_select, Float32Select) \
|
||||
V(float64_select, Float64Select) \
|
||||
V(int32_abs_with_overflow, Int32AbsWithOverflow) \
|
||||
V(int64_abs_with_overflow, Int64AbsWithOverflow) \
|
||||
V(word32_rol, Word32Rol) \
|
||||
V(word64_rol, Word64Rol) \
|
||||
V(word64_rol_lowerable, Word64RolLowerable) \
|
||||
V(sat_conversion_is_safe, SatConversionIsSafe) \
|
||||
V(word32_select, Word32Select) \
|
||||
V(word64_select, Word64Select)
|
||||
|
||||
class SupportedOperations {
|
||||
#define DECLARE_FIELD(name, machine_name) bool name##_;
|
||||
#define DECLARE_GETTER(name, machine_name) \
|
||||
static bool name() { \
|
||||
if constexpr (DEBUG_BOOL) { \
|
||||
base::MutexGuard lock(mutex_.Pointer()); \
|
||||
DCHECK(initialized_); \
|
||||
} \
|
||||
return instance_.name##_; \
|
||||
}
|
||||
|
||||
public:
|
||||
static void Initialize();
|
||||
SUPPORTED_OPERATIONS_LIST(DECLARE_GETTER)
|
||||
|
||||
private:
|
||||
SUPPORTED_OPERATIONS_LIST(DECLARE_FIELD)
|
||||
|
||||
static bool initialized_;
|
||||
static base::LazyMutex mutex_;
|
||||
static SupportedOperations instance_;
|
||||
|
||||
#undef DECLARE_FIELD
|
||||
#undef DECLARE_GETTER
|
||||
};
|
||||
|
||||
struct WordBinopOp : FixedArityOperationT<2, WordBinopOp> {
|
||||
enum class Kind : uint8_t {
|
||||
kAdd,
|
||||
kMul,
|
||||
@ -479,15 +540,11 @@ struct BinopOp : FixedArityOperationT<2, BinopOp> {
|
||||
kBitwiseAnd,
|
||||
kBitwiseOr,
|
||||
kBitwiseXor,
|
||||
kMin,
|
||||
kMax,
|
||||
kSub,
|
||||
kSignedDiv,
|
||||
kUnsignedDiv,
|
||||
kSignedMod,
|
||||
kUnsignedMod,
|
||||
kPower,
|
||||
kAtan2,
|
||||
};
|
||||
Kind kind;
|
||||
MachineRepresentation rep;
|
||||
@ -506,16 +563,12 @@ struct BinopOp : FixedArityOperationT<2, BinopOp> {
|
||||
case Kind::kBitwiseAnd:
|
||||
case Kind::kBitwiseOr:
|
||||
case Kind::kBitwiseXor:
|
||||
case Kind::kMin:
|
||||
case Kind::kMax:
|
||||
return true;
|
||||
case Kind::kSub:
|
||||
case Kind::kSignedDiv:
|
||||
case Kind::kUnsignedDiv:
|
||||
case Kind::kSignedMod:
|
||||
case Kind::kUnsignedMod:
|
||||
case Kind::kPower:
|
||||
case Kind::kAtan2:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -530,8 +583,6 @@ struct BinopOp : FixedArityOperationT<2, BinopOp> {
|
||||
case Kind::kBitwiseAnd:
|
||||
case Kind::kBitwiseOr:
|
||||
case Kind::kBitwiseXor:
|
||||
case Kind::kMin:
|
||||
case Kind::kMax:
|
||||
return true;
|
||||
case Kind::kSignedMulOverflownBits:
|
||||
case Kind::kUnsignedMulOverflownBits:
|
||||
@ -540,8 +591,6 @@ struct BinopOp : FixedArityOperationT<2, BinopOp> {
|
||||
case Kind::kUnsignedDiv:
|
||||
case Kind::kSignedMod:
|
||||
case Kind::kUnsignedMod:
|
||||
case Kind::kPower:
|
||||
case Kind::kAtan2:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -563,18 +612,65 @@ struct BinopOp : FixedArityOperationT<2, BinopOp> {
|
||||
case Kind::kSignedMod:
|
||||
case Kind::kUnsignedMod:
|
||||
return false;
|
||||
case Kind::kMin:
|
||||
case Kind::kMax:
|
||||
case Kind::kPower:
|
||||
case Kind::kAtan2:
|
||||
// Doesn't apply to operations only supported on floating-point
|
||||
// representations.
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
BinopOp(OpIndex left, OpIndex right, Kind kind, MachineRepresentation rep)
|
||||
: Base(left, right), kind(kind), rep(rep) {}
|
||||
WordBinopOp(OpIndex left, OpIndex right, Kind kind, MachineRepresentation rep)
|
||||
: Base(left, right), kind(kind), rep(rep) {
|
||||
DCHECK_EQ(rep, any_of(MachineRepresentation::kWord32,
|
||||
MachineRepresentation::kWord64));
|
||||
DCHECK_IMPLIES(kind == any_of(Kind::kSignedMulOverflownBits,
|
||||
Kind::kUnsignedMulOverflownBits),
|
||||
rep == MachineRepresentation::kWord32);
|
||||
}
|
||||
auto options() const { return std::tuple{kind, rep}; }
|
||||
void PrintOptions(std::ostream& os) const;
|
||||
};
|
||||
|
||||
struct FloatBinopOp : FixedArityOperationT<2, FloatBinopOp> {
|
||||
enum class Kind : uint8_t {
|
||||
kAdd,
|
||||
kMul,
|
||||
kMin,
|
||||
kMax,
|
||||
kSub,
|
||||
kDiv,
|
||||
kMod,
|
||||
kPower,
|
||||
kAtan2,
|
||||
};
|
||||
Kind kind;
|
||||
MachineRepresentation rep;
|
||||
|
||||
static constexpr OpProperties properties = OpProperties::Pure();
|
||||
|
||||
OpIndex left() const { return input(0); }
|
||||
OpIndex right() const { return input(1); }
|
||||
|
||||
static bool IsCommutative(Kind kind) {
|
||||
switch (kind) {
|
||||
case Kind::kAdd:
|
||||
case Kind::kMul:
|
||||
case Kind::kMin:
|
||||
case Kind::kMax:
|
||||
return true;
|
||||
case Kind::kSub:
|
||||
case Kind::kDiv:
|
||||
case Kind::kMod:
|
||||
case Kind::kPower:
|
||||
case Kind::kAtan2:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
FloatBinopOp(OpIndex left, OpIndex right, Kind kind,
|
||||
MachineRepresentation rep)
|
||||
: Base(left, right), kind(kind), rep(rep) {
|
||||
DCHECK_EQ(rep, any_of(MachineRepresentation::kFloat32,
|
||||
MachineRepresentation::kFloat64));
|
||||
DCHECK_IMPLIES(kind == any_of(Kind::kPower, Kind::kAtan2, Kind::kMod),
|
||||
rep == MachineRepresentation::kFloat64);
|
||||
}
|
||||
auto options() const { return std::tuple{kind, rep}; }
|
||||
void PrintOptions(std::ostream& os) const;
|
||||
};
|
||||
@ -606,12 +702,14 @@ struct OverflowCheckedBinopOp
|
||||
|
||||
OverflowCheckedBinopOp(OpIndex left, OpIndex right, Kind kind,
|
||||
MachineRepresentation rep)
|
||||
: Base(left, right), kind(kind), rep(rep) {}
|
||||
: Base(left, right), kind(kind), rep(rep) {
|
||||
DCHECK_EQ(rep, MachineRepresentation::kWord32);
|
||||
}
|
||||
auto options() const { return std::tuple{kind, rep}; }
|
||||
void PrintOptions(std::ostream& os) const;
|
||||
};
|
||||
|
||||
struct IntegerUnaryOp : FixedArityOperationT<1, IntegerUnaryOp> {
|
||||
struct WordUnaryOp : FixedArityOperationT<1, WordUnaryOp> {
|
||||
enum class Kind : uint8_t {
|
||||
kReverseBytes,
|
||||
kCountLeadingZeros,
|
||||
@ -622,11 +720,14 @@ struct IntegerUnaryOp : FixedArityOperationT<1, IntegerUnaryOp> {
|
||||
|
||||
OpIndex input() const { return Base::input(0); }
|
||||
|
||||
explicit IntegerUnaryOp(OpIndex input, Kind kind, MachineRepresentation rep)
|
||||
: Base(input), kind(kind), rep(rep) {}
|
||||
explicit WordUnaryOp(OpIndex input, Kind kind, MachineRepresentation rep)
|
||||
: Base(input), kind(kind), rep(rep) {
|
||||
DCHECK_EQ(rep, any_of(MachineRepresentation::kWord32,
|
||||
MachineRepresentation::kWord64));
|
||||
}
|
||||
auto options() const { return std::tuple{kind, rep}; }
|
||||
};
|
||||
std::ostream& operator<<(std::ostream& os, IntegerUnaryOp::Kind kind);
|
||||
std::ostream& operator<<(std::ostream& os, WordUnaryOp::Kind kind);
|
||||
|
||||
struct FloatUnaryOp : FixedArityOperationT<1, FloatUnaryOp> {
|
||||
enum class Kind : uint8_t {
|
||||
@ -658,8 +759,14 @@ struct FloatUnaryOp : FixedArityOperationT<1, FloatUnaryOp> {
|
||||
|
||||
OpIndex input() const { return Base::input(0); }
|
||||
|
||||
static bool IsSupported(Kind kind, MachineRepresentation rep);
|
||||
|
||||
explicit FloatUnaryOp(OpIndex input, Kind kind, MachineRepresentation rep)
|
||||
: Base(input), kind(kind), rep(rep) {}
|
||||
: Base(input), kind(kind), rep(rep) {
|
||||
DCHECK_EQ(rep, any_of(MachineRepresentation::kFloat32,
|
||||
MachineRepresentation::kFloat64));
|
||||
DCHECK(IsSupported(kind, rep));
|
||||
}
|
||||
auto options() const { return std::tuple{kind, rep}; }
|
||||
};
|
||||
std::ostream& operator<<(std::ostream& os, FloatUnaryOp::Kind kind);
|
||||
@ -693,9 +800,26 @@ struct ShiftOp : FixedArityOperationT<2, ShiftOp> {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// The Word32 and Word64 versions of the operator compute the same result when
|
||||
// truncated to 32 bit.
|
||||
static bool AllowsWord64ToWord32Truncation(Kind kind) {
|
||||
switch (kind) {
|
||||
case Kind::kShiftLeft:
|
||||
return true;
|
||||
case Kind::kShiftRightArithmeticShiftOutZeros:
|
||||
case Kind::kShiftRightArithmetic:
|
||||
case Kind::kShiftRightLogical:
|
||||
case Kind::kRotateRight:
|
||||
case Kind::kRotateLeft:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ShiftOp(OpIndex left, OpIndex right, Kind kind, MachineRepresentation rep)
|
||||
: Base(left, right), kind(kind), rep(rep) {}
|
||||
: Base(left, right), kind(kind), rep(rep) {
|
||||
DCHECK_EQ(rep, any_of(MachineRepresentation::kWord32,
|
||||
MachineRepresentation::kWord64));
|
||||
}
|
||||
auto options() const { return std::tuple{kind, rep}; }
|
||||
};
|
||||
std::ostream& operator<<(std::ostream& os, ShiftOp::Kind kind);
|
||||
@ -735,7 +859,12 @@ struct ComparisonOp : FixedArityOperationT<2, ComparisonOp> {
|
||||
|
||||
ComparisonOp(OpIndex left, OpIndex right, Kind kind,
|
||||
MachineRepresentation rep)
|
||||
: Base(left, right), kind(kind), rep(rep) {}
|
||||
: Base(left, right), kind(kind), rep(rep) {
|
||||
DCHECK_EQ(rep, any_of(MachineRepresentation::kWord32,
|
||||
MachineRepresentation::kWord64,
|
||||
MachineRepresentation::kFloat32,
|
||||
MachineRepresentation::kFloat64));
|
||||
}
|
||||
auto options() const { return std::tuple{kind, rep}; }
|
||||
};
|
||||
std::ostream& operator<<(std::ostream& os, ComparisonOp::Kind kind);
|
||||
@ -746,16 +875,17 @@ struct ChangeOp : FixedArityOperationT<1, ChangeOp> {
|
||||
// precisely
|
||||
kSignedNarrowing,
|
||||
kUnsignedNarrowing,
|
||||
// reduce integer bit-width, resulting in a modulo operation
|
||||
kIntegerTruncate,
|
||||
// convert between different floating-point types
|
||||
kFloatConversion,
|
||||
// system-specific conversion to (un)signed number
|
||||
// conversion to signed integer, rounding towards zero,
|
||||
// overflow behavior system-specific
|
||||
kSignedFloatTruncate,
|
||||
kUnsignedFloatTruncate,
|
||||
// like kSignedFloatTruncate, but overflow guaranteed to result in the
|
||||
// minimal integer
|
||||
kSignedFloatTruncateOverflowToMin,
|
||||
// JS semantics float64 to word32 truncation
|
||||
// https://tc39.es/ecma262/#sec-touint32
|
||||
kJSFloatTruncate,
|
||||
// convert (un)signed integer to floating-point value
|
||||
kSignedToFloat,
|
||||
kUnsignedToFloat,
|
||||
@ -907,7 +1037,11 @@ struct ConstantOp : FixedArityOperationT<0, ConstantOp> {
|
||||
}
|
||||
|
||||
ConstantOp(Kind kind, Storage storage)
|
||||
: Base(), kind(kind), storage(storage) {}
|
||||
: Base(), kind(kind), storage(storage) {
|
||||
DCHECK_IMPLIES(
|
||||
kind == Kind::kWord32,
|
||||
storage.integral <= MaxUnsignedValue(MachineRepresentation::kWord32));
|
||||
}
|
||||
|
||||
uint64_t integral() const {
|
||||
DCHECK(kind == Kind::kWord32 || kind == Kind::kWord64);
|
||||
@ -1001,7 +1135,7 @@ struct ConstantOp : FixedArityOperationT<0, ConstantOp> {
|
||||
}
|
||||
}
|
||||
|
||||
bool IsIntegral(uint64_t value) const {
|
||||
bool IsWord(uint64_t value) const {
|
||||
switch (kind) {
|
||||
case Kind::kWord32:
|
||||
return static_cast<uint32_t>(value) == word32();
|
||||
@ -1405,6 +1539,9 @@ struct BranchOp : FixedArityOperationT<1, BranchOp> {
|
||||
auto options() const { return std::tuple{if_true, if_false}; }
|
||||
};
|
||||
|
||||
// `CatchExceptionOp` has to follow a `CallOp` with a subsequent
|
||||
// `CheckLazyDeoptOp`. It provides the exception value, which might only be used
|
||||
// from the `if_exception` successor.
|
||||
struct CatchExceptionOp : FixedArityOperationT<1, CatchExceptionOp> {
|
||||
Block* if_success;
|
||||
Block* if_exception;
|
||||
@ -1446,26 +1583,28 @@ struct SwitchOp : FixedArityOperationT<1, SwitchOp> {
|
||||
auto options() const { return std::tuple{cases, default_case}; }
|
||||
};
|
||||
|
||||
// Tuples are only used to lower operations with multiple outputs.
|
||||
// `TupleOp` should be folded away by subsequent `ProjectionOp`s.
|
||||
struct TupleOp : OperationT<TupleOp> {
|
||||
static constexpr OpProperties properties = OpProperties::Pure();
|
||||
|
||||
explicit TupleOp(base::Vector<const OpIndex> inputs) : Base(inputs) {}
|
||||
auto options() const { return std::tuple{}; }
|
||||
};
|
||||
|
||||
// For operations that produce multiple results, we use `ProjectionOp` to
|
||||
// distinguish them.
|
||||
struct ProjectionOp : FixedArityOperationT<1, ProjectionOp> {
|
||||
enum class Kind : uint8_t { kExceptionValue, kTuple };
|
||||
Kind kind;
|
||||
uint16_t index;
|
||||
|
||||
static constexpr OpProperties properties = OpProperties::Pure();
|
||||
|
||||
OpIndex input() const { return Base::input(0); }
|
||||
|
||||
ProjectionOp(OpIndex input, Kind kind, uint16_t index)
|
||||
: Base(input), kind(kind), index(index) {
|
||||
DCHECK_IMPLIES(kind != Kind::kTuple, index == 0);
|
||||
}
|
||||
auto options() const { return std::tuple{kind, index}; }
|
||||
ProjectionOp(OpIndex input, uint16_t index) : Base(input), index(index) {}
|
||||
auto options() const { return std::tuple{index}; }
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, ProjectionOp::Kind kind);
|
||||
|
||||
#define OPERATION_PROPERTIES_CASE(Name) Name##Op::properties,
|
||||
static constexpr OpProperties kOperationPropertiesTable[kNumberOfOpcodes] = {
|
||||
TURBOSHAFT_OPERATION_LIST(OPERATION_PROPERTIES_CASE)};
|
||||
|
@ -209,6 +209,7 @@ struct OptimizationPhase<Analyzer, Assembler>::Impl {
|
||||
}
|
||||
assembler.current_block()->SetDeferred(input_block.IsDeferred());
|
||||
for (OpIndex index : input_graph.OperationIndices(input_block)) {
|
||||
if (!assembler.current_block()) break;
|
||||
assembler.SetCurrentOrigin(index);
|
||||
OpIndex first_output_index = assembler.graph().next_operation_index();
|
||||
USE(first_output_index);
|
||||
@ -327,7 +328,7 @@ struct OptimizationPhase<Analyzer, Assembler>::Impl {
|
||||
// predecessors did not change. In kDominator order, the order of control
|
||||
// predecessor might or might not change.
|
||||
for (OpIndex input : base::Reversed(old_inputs)) {
|
||||
if (new_pred->Origin() == old_pred) {
|
||||
if (new_pred && new_pred->Origin() == old_pred) {
|
||||
new_inputs.push_back(MapToNewGraph(input));
|
||||
new_pred = new_pred->NeighboringPredecessor();
|
||||
}
|
||||
@ -398,6 +399,7 @@ struct OptimizationPhase<Analyzer, Assembler>::Impl {
|
||||
return assembler.Call(callee, base::VectorOf(arguments), op.descriptor);
|
||||
}
|
||||
OpIndex ReduceReturn(const ReturnOp& op) {
|
||||
// We very rarely have tuples longer than 4.
|
||||
auto return_values = MapToNewGraph<4>(op.return_values());
|
||||
return assembler.Return(MapToNewGraph(op.pop_count()),
|
||||
base::VectorOf(return_values));
|
||||
@ -406,8 +408,8 @@ struct OptimizationPhase<Analyzer, Assembler>::Impl {
|
||||
return assembler.OverflowCheckedBinop(
|
||||
MapToNewGraph(op.left()), MapToNewGraph(op.right()), op.kind, op.rep);
|
||||
}
|
||||
OpIndex ReduceIntegerUnary(const IntegerUnaryOp& op) {
|
||||
return assembler.IntegerUnary(MapToNewGraph(op.input()), op.kind, op.rep);
|
||||
OpIndex ReduceWordUnary(const WordUnaryOp& op) {
|
||||
return assembler.WordUnary(MapToNewGraph(op.input()), op.kind, op.rep);
|
||||
}
|
||||
OpIndex ReduceFloatUnary(const FloatUnaryOp& op) {
|
||||
return assembler.FloatUnary(MapToNewGraph(op.input()), op.kind, op.rep);
|
||||
@ -487,12 +489,19 @@ struct OptimizationPhase<Analyzer, Assembler>::Impl {
|
||||
MapToNewGraph(op.frame_state()), op.negated,
|
||||
op.parameters);
|
||||
}
|
||||
OpIndex ReduceProjection(const ProjectionOp& op) {
|
||||
return assembler.Projection(MapToNewGraph(op.input()), op.kind, op.index);
|
||||
OpIndex ReduceTuple(const TupleOp& op) {
|
||||
return assembler.Tuple(base::VectorOf(MapToNewGraph<4>(op.inputs())));
|
||||
}
|
||||
OpIndex ReduceBinop(const BinopOp& op) {
|
||||
return assembler.Binop(MapToNewGraph(op.left()), MapToNewGraph(op.right()),
|
||||
op.kind, op.rep);
|
||||
OpIndex ReduceProjection(const ProjectionOp& op) {
|
||||
return assembler.Projection(MapToNewGraph(op.input()), op.index);
|
||||
}
|
||||
OpIndex ReduceWordBinop(const WordBinopOp& op) {
|
||||
return assembler.WordBinop(MapToNewGraph(op.left()),
|
||||
MapToNewGraph(op.right()), op.kind, op.rep);
|
||||
}
|
||||
OpIndex ReduceFloatBinop(const FloatBinopOp& op) {
|
||||
return assembler.FloatBinop(MapToNewGraph(op.left()),
|
||||
MapToNewGraph(op.right()), op.kind, op.rep);
|
||||
}
|
||||
OpIndex ReduceUnreachable(const UnreachableOp& op) {
|
||||
return assembler.Unreachable();
|
||||
|
@ -127,9 +127,9 @@ RecreateScheduleResult ScheduleBuilder::Run() {
|
||||
current_input_block = █
|
||||
current_block = GetBlock(block);
|
||||
current_block->set_deferred(current_input_block->IsDeferred());
|
||||
for (const Operation& op : input_graph.operations(block)) {
|
||||
for (OpIndex op : input_graph.OperationIndices(block)) {
|
||||
DCHECK_NOT_NULL(current_block);
|
||||
ProcessOperation(op);
|
||||
ProcessOperation(input_graph.Get(op));
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,164 +165,84 @@ void ScheduleBuilder::ProcessOperation(const Operation& op) {
|
||||
}
|
||||
}
|
||||
|
||||
Node* ScheduleBuilder::ProcessOperation(const BinopOp& op) {
|
||||
Node* ScheduleBuilder::ProcessOperation(const WordBinopOp& op) {
|
||||
using Kind = WordBinopOp::Kind;
|
||||
const Operator* o;
|
||||
switch (op.rep) {
|
||||
case MachineRepresentation::kWord32:
|
||||
switch (op.kind) {
|
||||
case BinopOp::Kind::kAdd:
|
||||
case Kind::kAdd:
|
||||
o = machine.Int32Add();
|
||||
break;
|
||||
case BinopOp::Kind::kSub:
|
||||
case Kind::kSub:
|
||||
o = machine.Int32Sub();
|
||||
break;
|
||||
case BinopOp::Kind::kMul:
|
||||
case Kind::kMul:
|
||||
o = machine.Int32Mul();
|
||||
break;
|
||||
case BinopOp::Kind::kSignedMulOverflownBits:
|
||||
case Kind::kSignedMulOverflownBits:
|
||||
o = machine.Int32MulHigh();
|
||||
break;
|
||||
case BinopOp::Kind::kUnsignedMulOverflownBits:
|
||||
case Kind::kUnsignedMulOverflownBits:
|
||||
o = machine.Uint32MulHigh();
|
||||
break;
|
||||
case BinopOp::Kind::kSignedDiv:
|
||||
case Kind::kSignedDiv:
|
||||
o = machine.Int32Div();
|
||||
break;
|
||||
case BinopOp::Kind::kUnsignedDiv:
|
||||
case Kind::kUnsignedDiv:
|
||||
o = machine.Uint32Div();
|
||||
break;
|
||||
case BinopOp::Kind::kSignedMod:
|
||||
case Kind::kSignedMod:
|
||||
o = machine.Int32Mod();
|
||||
break;
|
||||
case BinopOp::Kind::kUnsignedMod:
|
||||
case Kind::kUnsignedMod:
|
||||
o = machine.Uint32Mod();
|
||||
break;
|
||||
case BinopOp::Kind::kBitwiseAnd:
|
||||
case Kind::kBitwiseAnd:
|
||||
o = machine.Word32And();
|
||||
break;
|
||||
case BinopOp::Kind::kBitwiseOr:
|
||||
case Kind::kBitwiseOr:
|
||||
o = machine.Word32Or();
|
||||
break;
|
||||
case BinopOp::Kind::kBitwiseXor:
|
||||
case Kind::kBitwiseXor:
|
||||
o = machine.Word32Xor();
|
||||
break;
|
||||
case BinopOp::Kind::kMin:
|
||||
case BinopOp::Kind::kMax:
|
||||
case BinopOp::Kind::kPower:
|
||||
case BinopOp::Kind::kAtan2:
|
||||
UNREACHABLE();
|
||||
}
|
||||
break;
|
||||
case MachineRepresentation::kWord64:
|
||||
switch (op.kind) {
|
||||
case BinopOp::Kind::kAdd:
|
||||
case Kind::kAdd:
|
||||
o = machine.Int64Add();
|
||||
break;
|
||||
case BinopOp::Kind::kSub:
|
||||
case Kind::kSub:
|
||||
o = machine.Int64Sub();
|
||||
break;
|
||||
case BinopOp::Kind::kMul:
|
||||
case Kind::kMul:
|
||||
o = machine.Int64Mul();
|
||||
break;
|
||||
case BinopOp::Kind::kSignedDiv:
|
||||
case Kind::kSignedDiv:
|
||||
o = machine.Int64Div();
|
||||
break;
|
||||
case BinopOp::Kind::kUnsignedDiv:
|
||||
case Kind::kUnsignedDiv:
|
||||
o = machine.Uint64Div();
|
||||
break;
|
||||
case BinopOp::Kind::kSignedMod:
|
||||
case Kind::kSignedMod:
|
||||
o = machine.Int64Mod();
|
||||
break;
|
||||
case BinopOp::Kind::kUnsignedMod:
|
||||
case Kind::kUnsignedMod:
|
||||
o = machine.Uint64Mod();
|
||||
break;
|
||||
case BinopOp::Kind::kBitwiseAnd:
|
||||
case Kind::kBitwiseAnd:
|
||||
o = machine.Word64And();
|
||||
break;
|
||||
case BinopOp::Kind::kBitwiseOr:
|
||||
case Kind::kBitwiseOr:
|
||||
o = machine.Word64Or();
|
||||
break;
|
||||
case BinopOp::Kind::kBitwiseXor:
|
||||
case Kind::kBitwiseXor:
|
||||
o = machine.Word64Xor();
|
||||
break;
|
||||
case BinopOp::Kind::kMin:
|
||||
case BinopOp::Kind::kMax:
|
||||
case BinopOp::Kind::kSignedMulOverflownBits:
|
||||
case BinopOp::Kind::kUnsignedMulOverflownBits:
|
||||
case BinopOp::Kind::kPower:
|
||||
case BinopOp::Kind::kAtan2:
|
||||
UNREACHABLE();
|
||||
}
|
||||
break;
|
||||
case MachineRepresentation::kFloat32:
|
||||
switch (op.kind) {
|
||||
case BinopOp::Kind::kAdd:
|
||||
o = machine.Float32Add();
|
||||
break;
|
||||
case BinopOp::Kind::kSub:
|
||||
o = machine.Float32Sub();
|
||||
break;
|
||||
case BinopOp::Kind::kMul:
|
||||
o = machine.Float32Mul();
|
||||
break;
|
||||
case BinopOp::Kind::kSignedDiv:
|
||||
o = machine.Float32Div();
|
||||
break;
|
||||
case BinopOp::Kind::kMin:
|
||||
o = machine.Float32Min();
|
||||
break;
|
||||
case BinopOp::Kind::kMax:
|
||||
o = machine.Float32Max();
|
||||
break;
|
||||
case BinopOp::Kind::kSignedMulOverflownBits:
|
||||
case BinopOp::Kind::kUnsignedMulOverflownBits:
|
||||
case BinopOp::Kind::kUnsignedDiv:
|
||||
case BinopOp::Kind::kSignedMod:
|
||||
case BinopOp::Kind::kUnsignedMod:
|
||||
case BinopOp::Kind::kBitwiseAnd:
|
||||
case BinopOp::Kind::kBitwiseOr:
|
||||
case BinopOp::Kind::kBitwiseXor:
|
||||
case BinopOp::Kind::kPower:
|
||||
case BinopOp::Kind::kAtan2:
|
||||
UNREACHABLE();
|
||||
}
|
||||
break;
|
||||
case MachineRepresentation::kFloat64:
|
||||
switch (op.kind) {
|
||||
case BinopOp::Kind::kAdd:
|
||||
o = machine.Float64Add();
|
||||
break;
|
||||
case BinopOp::Kind::kSub:
|
||||
o = machine.Float64Sub();
|
||||
break;
|
||||
case BinopOp::Kind::kMul:
|
||||
o = machine.Float64Mul();
|
||||
break;
|
||||
case BinopOp::Kind::kSignedDiv:
|
||||
o = machine.Float64Div();
|
||||
break;
|
||||
case BinopOp::Kind::kSignedMod:
|
||||
o = machine.Float64Mod();
|
||||
break;
|
||||
case BinopOp::Kind::kMin:
|
||||
o = machine.Float64Min();
|
||||
break;
|
||||
case BinopOp::Kind::kMax:
|
||||
o = machine.Float64Max();
|
||||
break;
|
||||
case BinopOp::Kind::kPower:
|
||||
o = machine.Float64Pow();
|
||||
break;
|
||||
case BinopOp::Kind::kAtan2:
|
||||
o = machine.Float64Atan2();
|
||||
break;
|
||||
case BinopOp::Kind::kSignedMulOverflownBits:
|
||||
case BinopOp::Kind::kUnsignedMulOverflownBits:
|
||||
case BinopOp::Kind::kBitwiseAnd:
|
||||
case BinopOp::Kind::kBitwiseOr:
|
||||
case BinopOp::Kind::kBitwiseXor:
|
||||
case BinopOp::Kind::kUnsignedDiv:
|
||||
case BinopOp::Kind::kUnsignedMod:
|
||||
case Kind::kSignedMulOverflownBits:
|
||||
case Kind::kUnsignedMulOverflownBits:
|
||||
UNREACHABLE();
|
||||
}
|
||||
break;
|
||||
@ -331,6 +251,73 @@ Node* ScheduleBuilder::ProcessOperation(const BinopOp& op) {
|
||||
}
|
||||
return AddNode(o, {GetNode(op.left()), GetNode(op.right())});
|
||||
}
|
||||
Node* ScheduleBuilder::ProcessOperation(const FloatBinopOp& op) {
|
||||
using Kind = FloatBinopOp::Kind;
|
||||
const Operator* o;
|
||||
switch (op.rep) {
|
||||
case MachineRepresentation::kFloat32:
|
||||
switch (op.kind) {
|
||||
case Kind::kAdd:
|
||||
o = machine.Float32Add();
|
||||
break;
|
||||
case Kind::kSub:
|
||||
o = machine.Float32Sub();
|
||||
break;
|
||||
case Kind::kMul:
|
||||
o = machine.Float32Mul();
|
||||
break;
|
||||
case Kind::kDiv:
|
||||
o = machine.Float32Div();
|
||||
break;
|
||||
case Kind::kMin:
|
||||
o = machine.Float32Min();
|
||||
break;
|
||||
case Kind::kMax:
|
||||
o = machine.Float32Max();
|
||||
break;
|
||||
case Kind::kPower:
|
||||
case Kind::kAtan2:
|
||||
case Kind::kMod:
|
||||
UNREACHABLE();
|
||||
}
|
||||
break;
|
||||
case MachineRepresentation::kFloat64:
|
||||
switch (op.kind) {
|
||||
case Kind::kAdd:
|
||||
o = machine.Float64Add();
|
||||
break;
|
||||
case Kind::kSub:
|
||||
o = machine.Float64Sub();
|
||||
break;
|
||||
case Kind::kMul:
|
||||
o = machine.Float64Mul();
|
||||
break;
|
||||
case Kind::kDiv:
|
||||
o = machine.Float64Div();
|
||||
break;
|
||||
case Kind::kMod:
|
||||
o = machine.Float64Mod();
|
||||
break;
|
||||
case Kind::kMin:
|
||||
o = machine.Float64Min();
|
||||
break;
|
||||
case Kind::kMax:
|
||||
o = machine.Float64Max();
|
||||
break;
|
||||
case Kind::kPower:
|
||||
o = machine.Float64Pow();
|
||||
break;
|
||||
case Kind::kAtan2:
|
||||
o = machine.Float64Atan2();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return AddNode(o, {GetNode(op.left()), GetNode(op.right())});
|
||||
}
|
||||
|
||||
Node* ScheduleBuilder::ProcessOperation(const OverflowCheckedBinopOp& op) {
|
||||
const Operator* o;
|
||||
switch (op.rep) {
|
||||
@ -364,16 +351,16 @@ Node* ScheduleBuilder::ProcessOperation(const OverflowCheckedBinopOp& op) {
|
||||
}
|
||||
return AddNode(o, {GetNode(op.left()), GetNode(op.right())});
|
||||
}
|
||||
Node* ScheduleBuilder::ProcessOperation(const IntegerUnaryOp& op) {
|
||||
Node* ScheduleBuilder::ProcessOperation(const WordUnaryOp& op) {
|
||||
DCHECK(op.rep == MachineRepresentation::kWord32 ||
|
||||
op.rep == MachineRepresentation::kWord64);
|
||||
bool word64 = op.rep == MachineRepresentation::kWord64;
|
||||
const Operator* o;
|
||||
switch (op.kind) {
|
||||
case IntegerUnaryOp::Kind::kReverseBytes:
|
||||
case WordUnaryOp::Kind::kReverseBytes:
|
||||
o = word64 ? machine.Word64ReverseBytes() : machine.Word32ReverseBytes();
|
||||
break;
|
||||
case IntegerUnaryOp::Kind::kCountLeadingZeros:
|
||||
case WordUnaryOp::Kind::kCountLeadingZeros:
|
||||
o = word64 ? machine.Word64Clz() : machine.Word32Clz();
|
||||
break;
|
||||
}
|
||||
@ -587,14 +574,6 @@ Node* ScheduleBuilder::ProcessOperation(const ChangeOp& op) {
|
||||
const Operator* o;
|
||||
switch (op.kind) {
|
||||
using Kind = ChangeOp::Kind;
|
||||
case Kind::kIntegerTruncate:
|
||||
if (op.from == MachineRepresentation::kWord64 &&
|
||||
op.to == MachineRepresentation::kWord32) {
|
||||
o = machine.TruncateInt64ToInt32();
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
break;
|
||||
case Kind::kFloatConversion:
|
||||
if (op.from == MachineRepresentation::kFloat64 &&
|
||||
op.to == MachineRepresentation::kFloat32) {
|
||||
@ -625,7 +604,7 @@ Node* ScheduleBuilder::ProcessOperation(const ChangeOp& op) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
break;
|
||||
case Kind::kUnsignedFloatTruncate:
|
||||
case Kind::kJSFloatTruncate:
|
||||
if (op.from == MachineRepresentation::kFloat64 &&
|
||||
op.to == MachineRepresentation::kWord32) {
|
||||
o = machine.TruncateFloat64ToWord32();
|
||||
@ -749,6 +728,11 @@ Node* ScheduleBuilder::ProcessOperation(const TaggedBitcastOp& op) {
|
||||
Node* ScheduleBuilder::ProcessOperation(const PendingLoopPhiOp& op) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
Node* ScheduleBuilder::ProcessOperation(const TupleOp& op) {
|
||||
// Tuples are only used for lowerings during reduction. Therefore, we can
|
||||
// assume that it is unused if it occurs at this point.
|
||||
return nullptr;
|
||||
}
|
||||
Node* ScheduleBuilder::ProcessOperation(const ConstantOp& op) {
|
||||
switch (op.kind) {
|
||||
case ConstantOp::Kind::kWord32:
|
||||
@ -937,22 +921,7 @@ Node* ScheduleBuilder::ProcessOperation(const PhiOp& op) {
|
||||
}
|
||||
}
|
||||
Node* ScheduleBuilder::ProcessOperation(const ProjectionOp& op) {
|
||||
switch (op.kind) {
|
||||
case ProjectionOp::Kind::kTuple:
|
||||
return AddNode(common.Projection(op.index), {GetNode(op.input())});
|
||||
case ProjectionOp::Kind::kExceptionValue: {
|
||||
// The `IfException` projection was created when processing
|
||||
// `CatchExceptionOp`, so we just need to find it here.
|
||||
Node* call = GetNode(op.input());
|
||||
DCHECK_EQ(call->opcode(), IrOpcode::kCall);
|
||||
for (Node* use : call->uses()) {
|
||||
if (use->opcode() == IrOpcode::kIfException) {
|
||||
return use;
|
||||
}
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
return AddNode(common.Projection(op.index), {GetNode(op.input())});
|
||||
}
|
||||
|
||||
std::pair<Node*, MachineType> ScheduleBuilder::BuildDeoptInput(
|
||||
@ -1118,12 +1087,12 @@ Node* ScheduleBuilder::ProcessOperation(const CatchExceptionOp& op) {
|
||||
BasicBlock* exception_block = GetBlock(*op.if_exception);
|
||||
schedule->AddCall(current_block, call, success_block, exception_block);
|
||||
Node* if_success = MakeNode(common.IfSuccess(), {call});
|
||||
Node* if_exception = MakeNode(common.IfException(), {call, call});
|
||||
schedule->AddNode(success_block, if_success);
|
||||
// Pass `call` as both the effect and control input of `IfException`.
|
||||
schedule->AddNode(exception_block,
|
||||
MakeNode(common.IfException(), {call, call}));
|
||||
schedule->AddNode(exception_block, if_exception);
|
||||
current_block = nullptr;
|
||||
return if_success;
|
||||
return if_exception;
|
||||
}
|
||||
Node* ScheduleBuilder::ProcessOperation(const SwitchOp& op) {
|
||||
size_t succ_count = op.cases.size() + 1;
|
||||
|
91
src/compiler/turboshaft/utils.h
Normal file
91
src/compiler/turboshaft/utils.h
Normal file
@ -0,0 +1,91 @@
|
||||
// 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.
|
||||
|
||||
#ifndef V8_COMPILER_TURBOSHAFT_UTILS_H_
|
||||
#define V8_COMPILER_TURBOSHAFT_UTILS_H_
|
||||
|
||||
#include <iostream>
|
||||
#include <tuple>
|
||||
|
||||
#include "src/base/logging.h"
|
||||
|
||||
namespace v8::internal::compiler::turboshaft {
|
||||
|
||||
template <class... Ts>
|
||||
struct any_of : std::tuple<const Ts&...> {
|
||||
explicit any_of(const Ts&... args) : std::tuple<const Ts&...>(args...) {}
|
||||
|
||||
template <class T, size_t... indices>
|
||||
bool Contains(const T& value, std::index_sequence<indices...>) {
|
||||
return ((value == std::get<indices>(*this)) || ...);
|
||||
}
|
||||
|
||||
template <size_t... indices>
|
||||
std::ostream& PrintTo(std::ostream& os, std::index_sequence<indices...>) {
|
||||
bool first = true;
|
||||
os << "any_of(";
|
||||
(((first ? (first = false, os) : os << ", "),
|
||||
os << base::PrintCheckOperand(std::get<indices>(*this))),
|
||||
...);
|
||||
return os << ")";
|
||||
}
|
||||
};
|
||||
template <class... Args>
|
||||
any_of(const Args&...) -> any_of<Args...>;
|
||||
|
||||
template <class T, class... Ts>
|
||||
bool operator==(const T& value, any_of<Ts...> options) {
|
||||
return options.Contains(value, std::index_sequence_for<Ts...>{});
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
std::ostream& operator<<(std::ostream& os, any_of<Ts...> any) {
|
||||
return any.PrintTo(os, std::index_sequence_for<Ts...>{});
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
struct all_of : std::tuple<const Ts&...> {
|
||||
explicit all_of(const Ts&... args) : std::tuple<const Ts&...>(args...) {}
|
||||
|
||||
template <class T, size_t... indices>
|
||||
bool AllEqualTo(const T& value, std::index_sequence<indices...>) {
|
||||
return ((value == std::get<indices>(*this)) && ...);
|
||||
}
|
||||
|
||||
template <class T, size_t... indices>
|
||||
bool AllNotEqualTo(const T& value, std::index_sequence<indices...>) {
|
||||
return ((value != std::get<indices>(*this)) && ...);
|
||||
}
|
||||
|
||||
template <size_t... indices>
|
||||
std::ostream& PrintTo(std::ostream& os, std::index_sequence<indices...>) {
|
||||
bool first = true;
|
||||
os << "all_of(";
|
||||
(((first ? (first = false, os) : os << ", "),
|
||||
os << base::PrintCheckOperand(std::get<indices>(*this))),
|
||||
...);
|
||||
return os << ")";
|
||||
}
|
||||
};
|
||||
template <class... Args>
|
||||
all_of(const Args&...) -> all_of<Args...>;
|
||||
|
||||
template <class T, class... Ts>
|
||||
bool operator==(all_of<Ts...> values, const T& target) {
|
||||
return values.AllEqualTo(target, std::index_sequence_for<Ts...>{});
|
||||
}
|
||||
|
||||
template <class T, class... Ts>
|
||||
bool operator!=(const T& target, all_of<Ts...> values) {
|
||||
return values.AllNotEqualTo(target, std::index_sequence_for<Ts...>{});
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
std::ostream& operator<<(std::ostream& os, all_of<Ts...> all) {
|
||||
return all.PrintTo(os, std::index_sequence_for<Ts...>{});
|
||||
}
|
||||
|
||||
} // namespace v8::internal::compiler::turboshaft
|
||||
|
||||
#endif // V8_COMPILER_TURBOSHAFT_UTILS_H_
|
Loading…
Reference in New Issue
Block a user