[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:
Tobias Tebbi 2022-08-31 11:00:37 +02:00 committed by V8 LUCI CQ
parent 156c302fda
commit 7a61dad0db
13 changed files with 941 additions and 810 deletions

View File

@ -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",

View File

@ -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",

View File

@ -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;

View File

@ -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;

View File

@ -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_;

View File

@ -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_; }

View File

@ -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());

View File

@ -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:

View File

@ -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

View File

@ -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)};

View File

@ -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();

View File

@ -127,9 +127,9 @@ RecreateScheduleResult ScheduleBuilder::Run() {
current_input_block = &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;

View 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_