diff --git a/src/compiler/common-operator.cc b/src/compiler/common-operator.cc index 96a8d54964..4f5ead89eb 100644 --- a/src/compiler/common-operator.cc +++ b/src/compiler/common-operator.cc @@ -469,7 +469,7 @@ struct CommonOperatorGlobalCache final { IrOpcode::kProjection, // opcode Operator::kPure, // flags "Projection", // name - 1, 0, 0, 1, 0, 0, // counts, + 1, 0, 1, 1, 0, 0, // counts, kIndex) {} // parameter }; #define CACHED_PROJECTION(index) \ @@ -915,12 +915,12 @@ const Operator* CommonOperatorBuilder::Projection(size_t index) { break; } // Uncached. - return new (zone()) Operator1( // -- - IrOpcode::kProjection, // opcode - Operator::kFoldable | Operator::kNoThrow, // flags - "Projection", // name - 1, 0, 0, 1, 0, 0, // counts - index); // parameter + return new (zone()) Operator1( // -- + IrOpcode::kProjection, // opcode + Operator::kPure, // flags + "Projection", // name + 1, 0, 1, 1, 0, 0, // counts + index); // parameter } diff --git a/src/compiler/effect-control-linearizer.cc b/src/compiler/effect-control-linearizer.cc index 44f428d175..b7f6b129e5 100644 --- a/src/compiler/effect-control-linearizer.cc +++ b/src/compiler/effect-control-linearizer.cc @@ -440,6 +440,12 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node, case IrOpcode::kCheckTaggedSigned: state = LowerCheckTaggedSigned(node, frame_state, *effect, *control); break; + case IrOpcode::kCheckedInt32Add: + state = LowerCheckedInt32Add(node, frame_state, *effect, *control); + break; + case IrOpcode::kCheckedInt32Sub: + state = LowerCheckedInt32Sub(node, frame_state, *effect, *control); + break; case IrOpcode::kCheckedUint32ToInt32: state = LowerCheckedUint32ToInt32(node, frame_state, *effect, *control); break; @@ -476,9 +482,6 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node, case IrOpcode::kStringFromCharCode: state = LowerStringFromCharCode(node, *effect, *control); break; - case IrOpcode::kCheckIf: - state = LowerCheckIf(node, frame_state, *effect, *control); - break; case IrOpcode::kCheckFloat64Hole: state = LowerCheckFloat64Hole(node, frame_state, *effect, *control); break; @@ -554,10 +557,11 @@ EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node, Node* effect, if (machine()->Is64()) { vsmi = ChangeInt32ToSmi(value32); } else { - Node* smi_tag = - graph()->NewNode(machine()->Int32AddWithOverflow(), value32, value32); + Node* smi_tag = graph()->NewNode(machine()->Int32AddWithOverflow(), value32, + value32, if_smi); - Node* check_ovf = graph()->NewNode(common()->Projection(1), smi_tag); + Node* check_ovf = + graph()->NewNode(common()->Projection(1), smi_tag, if_smi); Node* branch_ovf = graph()->NewNode(common()->Branch(BranchHint::kFalse), check_ovf, if_smi); @@ -565,7 +569,7 @@ EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node, Node* effect, if_box = graph()->NewNode(common()->Merge(2), if_ovf, if_box); if_smi = graph()->NewNode(common()->IfFalse(), branch_ovf); - vsmi = graph()->NewNode(common()->Projection(0), smi_tag); + vsmi = graph()->NewNode(common()->Projection(0), smi_tag, if_smi); } // Allocate the box for the {value}. @@ -617,9 +621,10 @@ EffectControlLinearizer::LowerChangeInt32ToTagged(Node* node, Node* effect, return ValueEffectControl(ChangeInt32ToSmi(value), effect, control); } - Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), value, value); + Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), value, value, + control); - Node* ovf = graph()->NewNode(common()->Projection(1), add); + Node* ovf = graph()->NewNode(common()->Projection(1), add, control); Node* branch = graph()->NewNode(common()->Branch(BranchHint::kFalse), ovf, control); @@ -628,7 +633,7 @@ EffectControlLinearizer::LowerChangeInt32ToTagged(Node* node, Node* effect, AllocateHeapNumberWithValue(ChangeInt32ToFloat64(value), effect, if_true); Node* if_false = graph()->NewNode(common()->IfFalse(), branch); - Node* vfalse = graph()->NewNode(common()->Projection(0), add); + Node* vfalse = graph()->NewNode(common()->Projection(0), add, if_false); Node* merge = graph()->NewNode(common()->Merge(2), alloc.control, if_false); Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), @@ -834,6 +839,48 @@ EffectControlLinearizer::LowerCheckTaggedSigned(Node* node, Node* frame_state, return ValueEffectControl(value, effect, control); } +EffectControlLinearizer::ValueEffectControl +EffectControlLinearizer::LowerCheckedInt32Add(Node* node, Node* frame_state, + Node* effect, Node* control) { + Node* lhs = node->InputAt(0); + Node* rhs = node->InputAt(1); + + Node* value = + graph()->NewNode(machine()->Int32AddWithOverflow(), lhs, rhs, control); + + Node* check = graph()->NewNode(common()->Projection(1), value, control); + control = effect = graph()->NewNode(common()->DeoptimizeIf(), check, + frame_state, effect, control); + + value = graph()->NewNode(common()->Projection(0), value, control); + + // Make sure the lowered node does not appear in any use lists. + node->TrimInputCount(0); + + return ValueEffectControl(value, effect, control); +} + +EffectControlLinearizer::ValueEffectControl +EffectControlLinearizer::LowerCheckedInt32Sub(Node* node, Node* frame_state, + Node* effect, Node* control) { + Node* lhs = node->InputAt(0); + Node* rhs = node->InputAt(1); + + Node* value = + graph()->NewNode(machine()->Int32SubWithOverflow(), lhs, rhs, control); + + Node* check = graph()->NewNode(common()->Projection(1), value, control); + control = effect = graph()->NewNode(common()->DeoptimizeIf(), check, + frame_state, effect, control); + + value = graph()->NewNode(common()->Projection(0), value, control); + + // Make sure the lowered node does not appear in any use lists. + node->TrimInputCount(0); + + return ValueEffectControl(value, effect, control); +} + EffectControlLinearizer::ValueEffectControl EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node, Node* frame_state, @@ -1371,17 +1418,6 @@ EffectControlLinearizer::LowerStringFromCharCode(Node* node, Node* effect, return ValueEffectControl(value, effect, control); } -EffectControlLinearizer::ValueEffectControl -EffectControlLinearizer::LowerCheckIf(Node* node, Node* frame_state, - Node* effect, Node* control) { - NodeProperties::ReplaceEffectInput(node, effect); - NodeProperties::ReplaceControlInput(node, control); - DCHECK_NOT_NULL(frame_state); - node->InsertInput(graph()->zone(), 1, frame_state); - NodeProperties::ChangeOp(node, common()->DeoptimizeIf()); - return ValueEffectControl(node, node, node); -} - EffectControlLinearizer::ValueEffectControl EffectControlLinearizer::LowerCheckFloat64Hole(Node* node, Node* frame_state, Node* effect, Node* control) { diff --git a/src/compiler/effect-control-linearizer.h b/src/compiler/effect-control-linearizer.h index 8b53ce0692..280b4b7735 100644 --- a/src/compiler/effect-control-linearizer.h +++ b/src/compiler/effect-control-linearizer.h @@ -68,6 +68,10 @@ class EffectControlLinearizer { Node* effect, Node* control); ValueEffectControl LowerCheckTaggedSigned(Node* node, Node* frame_state, Node* effect, Node* control); + ValueEffectControl LowerCheckedInt32Add(Node* node, Node* frame_state, + Node* effect, Node* control); + ValueEffectControl LowerCheckedInt32Sub(Node* node, Node* frame_state, + Node* effect, Node* control); ValueEffectControl LowerCheckedUint32ToInt32(Node* node, Node* frame_state, Node* effect, Node* control); ValueEffectControl LowerCheckedFloat64ToInt32(Node* node, Node* frame_state, @@ -99,8 +103,6 @@ class EffectControlLinearizer { Node* effect, Node* control); ValueEffectControl LowerCheckTaggedHole(Node* node, Node* frame_state, Node* effect, Node* control); - ValueEffectControl LowerCheckIf(Node* node, Node* frame_state, Node* effect, - Node* control); ValueEffectControl LowerPlainPrimitiveToNumber(Node* node, Node* effect, Node* control); ValueEffectControl LowerPlainPrimitiveToWord32(Node* node, Node* effect, diff --git a/src/compiler/int64-lowering.cc b/src/compiler/int64-lowering.cc index 71f500886b..a5f9cf075d 100644 --- a/src/compiler/int64-lowering.cc +++ b/src/compiler/int64-lowering.cc @@ -243,8 +243,10 @@ void Int64Lowering::LowerNode(Node* node) { if (descriptor->ReturnCount() == 1 && descriptor->GetReturnType(0) == MachineType::Int64()) { // We access the additional return values through projections. - Node* low_node = graph()->NewNode(common()->Projection(0), node); - Node* high_node = graph()->NewNode(common()->Projection(1), node); + Node* low_node = + graph()->NewNode(common()->Projection(0), node, graph()->start()); + Node* high_node = + graph()->NewNode(common()->Projection(1), node, graph()->start()); ReplaceNode(node, low_node, high_node); } break; @@ -283,8 +285,10 @@ void Int64Lowering::LowerNode(Node* node) { NodeProperties::ChangeOp(node, machine()->Int32PairAdd()); // We access the additional return values through projections. - Node* low_node = graph()->NewNode(common()->Projection(0), node); - Node* high_node = graph()->NewNode(common()->Projection(1), node); + Node* low_node = + graph()->NewNode(common()->Projection(0), node, graph()->start()); + Node* high_node = + graph()->NewNode(common()->Projection(1), node, graph()->start()); ReplaceNode(node, low_node, high_node); break; } @@ -301,8 +305,10 @@ void Int64Lowering::LowerNode(Node* node) { NodeProperties::ChangeOp(node, machine()->Int32PairSub()); // We access the additional return values through projections. - Node* low_node = graph()->NewNode(common()->Projection(0), node); - Node* high_node = graph()->NewNode(common()->Projection(1), node); + Node* low_node = + graph()->NewNode(common()->Projection(0), node, graph()->start()); + Node* high_node = + graph()->NewNode(common()->Projection(1), node, graph()->start()); ReplaceNode(node, low_node, high_node); break; } @@ -319,8 +325,10 @@ void Int64Lowering::LowerNode(Node* node) { NodeProperties::ChangeOp(node, machine()->Int32PairMul()); // We access the additional return values through projections. - Node* low_node = graph()->NewNode(common()->Projection(0), node); - Node* high_node = graph()->NewNode(common()->Projection(1), node); + Node* low_node = + graph()->NewNode(common()->Projection(0), node, graph()->start()); + Node* high_node = + graph()->NewNode(common()->Projection(1), node, graph()->start()); ReplaceNode(node, low_node, high_node); break; } @@ -369,8 +377,10 @@ void Int64Lowering::LowerNode(Node* node) { NodeProperties::ChangeOp(node, machine()->Word32PairShl()); // We access the additional return values through projections. - Node* low_node = graph()->NewNode(common()->Projection(0), node); - Node* high_node = graph()->NewNode(common()->Projection(1), node); + Node* low_node = + graph()->NewNode(common()->Projection(0), node, graph()->start()); + Node* high_node = + graph()->NewNode(common()->Projection(1), node, graph()->start()); ReplaceNode(node, low_node, high_node); break; } @@ -391,8 +401,10 @@ void Int64Lowering::LowerNode(Node* node) { NodeProperties::ChangeOp(node, machine()->Word32PairShr()); // We access the additional return values through projections. - Node* low_node = graph()->NewNode(common()->Projection(0), node); - Node* high_node = graph()->NewNode(common()->Projection(1), node); + Node* low_node = + graph()->NewNode(common()->Projection(0), node, graph()->start()); + Node* high_node = + graph()->NewNode(common()->Projection(1), node, graph()->start()); ReplaceNode(node, low_node, high_node); break; } @@ -413,8 +425,10 @@ void Int64Lowering::LowerNode(Node* node) { NodeProperties::ChangeOp(node, machine()->Word32PairSar()); // We access the additional return values through projections. - Node* low_node = graph()->NewNode(common()->Projection(0), node); - Node* high_node = graph()->NewNode(common()->Projection(1), node); + Node* low_node = + graph()->NewNode(common()->Projection(0), node, graph()->start()); + Node* high_node = + graph()->NewNode(common()->Projection(1), node, graph()->start()); ReplaceNode(node, low_node, high_node); break; } diff --git a/src/compiler/machine-operator.cc b/src/compiler/machine-operator.cc index 61a15b2308..3662d0ab59 100644 --- a/src/compiler/machine-operator.cc +++ b/src/compiler/machine-operator.cc @@ -88,10 +88,7 @@ MachineRepresentation AtomicStoreRepresentationOf(Operator const* op) { V(Word64Clz, Operator::kNoProperties, 1, 0, 1) \ V(Word64Equal, Operator::kCommutative, 2, 0, 1) \ V(Int32Add, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \ - V(Int32AddWithOverflow, Operator::kAssociative | Operator::kCommutative, 2, \ - 0, 2) \ V(Int32Sub, Operator::kNoProperties, 2, 0, 1) \ - V(Int32SubWithOverflow, Operator::kNoProperties, 2, 0, 2) \ V(Int32Mul, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \ V(Int32MulHigh, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \ V(Int32Div, Operator::kNoProperties, 2, 1, 1) \ @@ -104,10 +101,7 @@ MachineRepresentation AtomicStoreRepresentationOf(Operator const* op) { V(Uint32Mod, Operator::kNoProperties, 2, 1, 1) \ V(Uint32MulHigh, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \ V(Int64Add, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \ - V(Int64AddWithOverflow, Operator::kAssociative | Operator::kCommutative, 2, \ - 0, 2) \ V(Int64Sub, Operator::kNoProperties, 2, 0, 1) \ - V(Int64SubWithOverflow, Operator::kNoProperties, 2, 0, 2) \ V(Int64Mul, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \ V(Int64Div, Operator::kNoProperties, 2, 1, 1) \ V(Int64Mod, Operator::kNoProperties, 2, 1, 1) \ @@ -390,6 +384,12 @@ MachineRepresentation AtomicStoreRepresentationOf(Operator const* op) { V(Float32Neg, Operator::kNoProperties, 1, 0, 1) \ V(Float64Neg, Operator::kNoProperties, 1, 0, 1) +#define OVERFLOW_OP_LIST(V) \ + V(Int32AddWithOverflow, Operator::kAssociative | Operator::kCommutative) \ + V(Int32SubWithOverflow, Operator::kNoProperties) \ + V(Int64AddWithOverflow, Operator::kAssociative | Operator::kCommutative) \ + V(Int64SubWithOverflow, Operator::kNoProperties) + #define MACHINE_TYPE_LIST(V) \ V(Float32) \ V(Float64) \ @@ -442,6 +442,17 @@ struct MachineOperatorGlobalCache { PURE_OPTIONAL_OP_LIST(PURE) #undef PURE +#define OVERFLOW_OP(Name, properties) \ + struct Name##Operator final : public Operator { \ + Name##Operator() \ + : Operator(IrOpcode::k##Name, \ + Operator::kEliminatable | Operator::kNoRead | properties, \ + #Name, 2, 0, 1, 2, 0, 0) {} \ + }; \ + Name##Operator k##Name; + OVERFLOW_OP_LIST(OVERFLOW_OP) +#undef OVERFLOW_OP + #define LOAD(Type) \ struct Load##Type##Operator final : public Operator1 { \ Load##Type##Operator() \ @@ -594,6 +605,10 @@ PURE_OP_LIST(PURE) PURE_OPTIONAL_OP_LIST(PURE) #undef PURE +#define OVERFLOW_OP(Name, properties) \ + const Operator* MachineOperatorBuilder::Name() { return &cache_.k##Name; } +OVERFLOW_OP_LIST(OVERFLOW_OP) +#undef OVERFLOW_OP const Operator* MachineOperatorBuilder::Load(LoadRepresentation rep) { #define LOAD(Type) \ diff --git a/src/compiler/opcodes.h b/src/compiler/opcodes.h index e1ae2d94fc..22ecec588f 100644 --- a/src/compiler/opcodes.h +++ b/src/compiler/opcodes.h @@ -238,13 +238,14 @@ V(CheckBounds) \ V(CheckTaggedPointer) \ V(CheckTaggedSigned) \ + V(CheckedInt32Add) \ + V(CheckedInt32Sub) \ V(CheckedUint32ToInt32) \ V(CheckedFloat64ToInt32) \ V(CheckedTaggedToInt32) \ V(CheckedTaggedToFloat64) \ V(CheckFloat64Hole) \ V(CheckTaggedHole) \ - V(CheckIf) \ V(TruncateTaggedToWord32) \ V(TruncateTaggedToFloat64) \ V(Allocate) \ diff --git a/src/compiler/representation-change.cc b/src/compiler/representation-change.cc index 61f363e77f..d05fa19a4d 100644 --- a/src/compiler/representation-change.cc +++ b/src/compiler/representation-change.cc @@ -604,9 +604,9 @@ const Operator* RepresentationChanger::Int32OverflowOperatorFor( IrOpcode::Value opcode) { switch (opcode) { case IrOpcode::kSpeculativeNumberAdd: // Fall through. - return machine()->Int32AddWithOverflow(); + return simplified()->CheckedInt32Add(); case IrOpcode::kSpeculativeNumberSubtract: // Fall through. - return machine()->Int32SubWithOverflow(); + return simplified()->CheckedInt32Sub(); default: UNREACHABLE(); return nullptr; diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc index ee1d7b7a81..343282ffee 100644 --- a/src/compiler/simplified-lowering.cc +++ b/src/compiler/simplified-lowering.cc @@ -1091,16 +1091,8 @@ class RepresentationSelector { NodeProperties::ChangeOp(node, new_op); } - void ChangeToInt32OverflowOp(Node* node, const Operator* op) { - Node* effect = NodeProperties::GetEffectInput(node); - Node* control = NodeProperties::GetControlInput(node); - Node* arith = graph()->NewNode(op, node->InputAt(0), node->InputAt(1)); - Node* overflow = graph()->NewNode(common()->Projection(1), arith); - effect = - graph()->NewNode(simplified()->CheckIf(), overflow, effect, control); - Node* value = graph()->NewNode(common()->Projection(0), arith); - ReplaceEffectControlUses(node, effect, control); - DeferReplacement(node, value); + void ChangeToInt32OverflowOp(Node* node, const Operator* new_op) { + NodeProperties::ChangeOp(node, new_op); } void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation, @@ -2037,6 +2029,8 @@ class RepresentationSelector { case IrOpcode::kChangeFloat64ToUint32: case IrOpcode::kTruncateInt64ToInt32: case IrOpcode::kChangeFloat32ToFloat64: + case IrOpcode::kCheckedInt32Add: + case IrOpcode::kCheckedInt32Sub: case IrOpcode::kCheckedUint32ToInt32: case IrOpcode::kCheckedFloat64ToInt32: case IrOpcode::kCheckedTaggedToInt32: diff --git a/src/compiler/simplified-operator.cc b/src/compiler/simplified-operator.cc index 08361e51e5..165ea415ab 100644 --- a/src/compiler/simplified-operator.cc +++ b/src/compiler/simplified-operator.cc @@ -308,13 +308,15 @@ CompareOperationHints::Hint CompareOperationHintOf(const Operator* op) { V(SpeculativeNumberMultiply) \ V(SpeculativeNumberModulus) -#define CHECKED_OP_LIST(V) \ - V(CheckTaggedPointer) \ - V(CheckTaggedSigned) \ - V(CheckedUint32ToInt32) \ - V(CheckedFloat64ToInt32) \ - V(CheckedTaggedToInt32) \ - V(CheckedTaggedToFloat64) +#define CHECKED_OP_LIST(V) \ + V(CheckTaggedPointer, 1) \ + V(CheckTaggedSigned, 1) \ + V(CheckedInt32Add, 2) \ + V(CheckedInt32Sub, 2) \ + V(CheckedUint32ToInt32, 1) \ + V(CheckedFloat64ToInt32, 1) \ + V(CheckedTaggedToInt32, 1) \ + V(CheckedTaggedToFloat64, 1) struct SimplifiedOperatorGlobalCache final { #define PURE(Name, properties, input_count) \ @@ -327,29 +329,29 @@ struct SimplifiedOperatorGlobalCache final { PURE_OP_LIST(PURE) #undef PURE -#define CHECKED(Name) \ - struct Name##Operator final : public Operator { \ - Name##Operator() \ - : Operator(IrOpcode::k##Name, \ - Operator::kFoldable | Operator::kNoThrow, #Name, 1, 1, 1, \ - 1, 1, 0) {} \ - }; \ +#define CHECKED(Name, value_input_count) \ + struct Name##Operator final : public Operator { \ + Name##Operator() \ + : Operator(IrOpcode::k##Name, \ + Operator::kFoldable | Operator::kNoThrow, #Name, \ + value_input_count, 1, 1, 1, 1, 0) {} \ + }; \ Name##Operator k##Name; CHECKED_OP_LIST(CHECKED) #undef CHECKED template - struct CheckFloat64HoleNaNOperatortor final + struct CheckFloat64HoleNaNOperator final : public Operator1 { - CheckFloat64HoleNaNOperatortor() + CheckFloat64HoleNaNOperator() : Operator1( IrOpcode::kCheckFloat64Hole, - Operator::kFoldable | Operator::kNoDeopt, "CheckFloat64Hole", 1, + Operator::kFoldable | Operator::kNoThrow, "CheckFloat64Hole", 1, 1, 1, 1, 1, 0, kMode) {} }; - CheckFloat64HoleNaNOperatortor + CheckFloat64HoleNaNOperator kCheckFloat64HoleAllowReturnHoleOperator; - CheckFloat64HoleNaNOperatortor + CheckFloat64HoleNaNOperator kCheckFloat64HoleNeverReturnHoleOperator; template @@ -357,7 +359,7 @@ struct SimplifiedOperatorGlobalCache final { CheckTaggedHoleOperator() : Operator1( IrOpcode::kCheckTaggedHole, - Operator::kFoldable | Operator::kNoDeopt, "CheckTaggedHole", 1, 1, + Operator::kFoldable | Operator::kNoThrow, "CheckTaggedHole", 1, 1, 1, 1, 1, 0, kMode) {} }; CheckTaggedHoleOperator @@ -365,13 +367,6 @@ struct SimplifiedOperatorGlobalCache final { CheckTaggedHoleOperator kCheckTaggedHoleNeverReturnHoleOperator; - struct CheckIfOperator final : public Operator { - CheckIfOperator() - : Operator(IrOpcode::kCheckIf, Operator::kFoldable | Operator::kNoDeopt, - "CheckIf", 1, 1, 1, 0, 1, 0) {} - }; - CheckIfOperator kCheckIf; - template struct AllocateOperator final : public Operator1 { AllocateOperator() @@ -419,7 +414,7 @@ SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone) PURE_OP_LIST(GET_FROM_CACHE) #undef GET_FROM_CACHE -#define GET_FROM_CACHE(Name) \ +#define GET_FROM_CACHE(Name, value_input_count) \ const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; } CHECKED_OP_LIST(GET_FROM_CACHE) #undef GET_FROM_CACHE @@ -448,10 +443,6 @@ const Operator* SimplifiedOperatorBuilder::CheckTaggedHole( return nullptr; } -const Operator* SimplifiedOperatorBuilder::CheckIf() { - return &cache_.kCheckIf; -} - const Operator* SimplifiedOperatorBuilder::ReferenceEqual(Type* type) { return new (zone()) Operator(IrOpcode::kReferenceEqual, Operator::kCommutative | Operator::kPure, diff --git a/src/compiler/simplified-operator.h b/src/compiler/simplified-operator.h index 31bcb687d4..79a2e2c128 100644 --- a/src/compiler/simplified-operator.h +++ b/src/compiler/simplified-operator.h @@ -240,6 +240,8 @@ class SimplifiedOperatorBuilder final : public ZoneObject { const Operator* CheckTaggedPointer(); const Operator* CheckTaggedSigned(); + const Operator* CheckedInt32Add(); + const Operator* CheckedInt32Sub(); const Operator* CheckedUint32ToInt32(); const Operator* CheckedFloat64ToInt32(); const Operator* CheckedTaggedToInt32(); @@ -247,7 +249,6 @@ class SimplifiedOperatorBuilder final : public ZoneObject { const Operator* CheckFloat64Hole(CheckFloat64HoleMode); const Operator* CheckTaggedHole(CheckTaggedHoleMode); - const Operator* CheckIf(); const Operator* ObjectIsCallable(); const Operator* ObjectIsNumber(); diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc index bfba6f9387..f684dd8fae 100644 --- a/src/compiler/typer.cc +++ b/src/compiler/typer.cc @@ -2018,6 +2018,14 @@ Type* Typer::Visitor::TypeCheckTaggedSigned(Node* node) { return Type::Intersect(arg, typer_->cache_.kSmi, zone()); } +Type* Typer::Visitor::TypeCheckedInt32Add(Node* node) { + return Type::Integral32(); +} + +Type* Typer::Visitor::TypeCheckedInt32Sub(Node* node) { + return Type::Integral32(); +} + Type* Typer::Visitor::TypeCheckedUint32ToInt32(Node* node) { return Type::Signed32(); } @@ -2057,11 +2065,6 @@ Type* Typer::Visitor::TypeCheckTaggedHole(Node* node) { return type; } -Type* Typer::Visitor::TypeCheckIf(Node* node) { - UNREACHABLE(); - return nullptr; -} - Type* Typer::Visitor::TypeTruncateTaggedToWord32(Node* node) { Type* arg = Operand(node, 0); // TODO(jarin): DCHECK(arg->Is(Type::NumberOrUndefined())); diff --git a/src/compiler/verifier.cc b/src/compiler/verifier.cc index 17b81df1e6..cb61108b64 100644 --- a/src/compiler/verifier.cc +++ b/src/compiler/verifier.cc @@ -278,7 +278,6 @@ void Verifier::Visitor::Check(Node* node) { break; case IrOpcode::kDeoptimizeIf: case IrOpcode::kDeoptimizeUnless: - case IrOpcode::kCheckIf: // Type is empty. CheckNotTyped(node); break; @@ -956,6 +955,8 @@ void Verifier::Visitor::Check(Node* node) { CheckUpperIs(node, Type::TaggedPointer()); break; + case IrOpcode::kCheckedInt32Add: + case IrOpcode::kCheckedInt32Sub: case IrOpcode::kCheckedUint32ToInt32: case IrOpcode::kCheckedFloat64ToInt32: case IrOpcode::kCheckedTaggedToInt32: diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc index 4b63414152..511367ee2a 100644 --- a/src/compiler/wasm-compiler.cc +++ b/src/compiler/wasm-compiler.cc @@ -1479,9 +1479,10 @@ Node* WasmGraphBuilder::BuildI64SConvertF32(Node* input, } else { Node* trunc = graph()->NewNode( jsgraph()->machine()->TryTruncateFloat32ToInt64(), input); - Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); - Node* overflow = - graph()->NewNode(jsgraph()->common()->Projection(1), trunc); + Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc, + graph()->start()); + Node* overflow = graph()->NewNode(jsgraph()->common()->Projection(1), trunc, + graph()->start()); trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position); return result; } @@ -1496,9 +1497,10 @@ Node* WasmGraphBuilder::BuildI64UConvertF32(Node* input, } else { Node* trunc = graph()->NewNode( jsgraph()->machine()->TryTruncateFloat32ToUint64(), input); - Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); - Node* overflow = - graph()->NewNode(jsgraph()->common()->Projection(1), trunc); + Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc, + graph()->start()); + Node* overflow = graph()->NewNode(jsgraph()->common()->Projection(1), trunc, + graph()->start()); trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position); return result; } @@ -1513,9 +1515,10 @@ Node* WasmGraphBuilder::BuildI64SConvertF64(Node* input, } else { Node* trunc = graph()->NewNode( jsgraph()->machine()->TryTruncateFloat64ToInt64(), input); - Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); - Node* overflow = - graph()->NewNode(jsgraph()->common()->Projection(1), trunc); + Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc, + graph()->start()); + Node* overflow = graph()->NewNode(jsgraph()->common()->Projection(1), trunc, + graph()->start()); trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position); return result; } @@ -1530,9 +1533,10 @@ Node* WasmGraphBuilder::BuildI64UConvertF64(Node* input, } else { Node* trunc = graph()->NewNode( jsgraph()->machine()->TryTruncateFloat64ToUint64(), input); - Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc); - Node* overflow = - graph()->NewNode(jsgraph()->common()->Projection(1), trunc); + Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc, + graph()->start()); + Node* overflow = graph()->NewNode(jsgraph()->common()->Projection(1), trunc, + graph()->start()); trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position); return result; } @@ -1975,9 +1979,10 @@ Node* WasmGraphBuilder::BuildChangeInt32ToTagged(Node* value) { return BuildChangeInt32ToSmi(value); } - Node* add = graph()->NewNode(machine->Int32AddWithOverflow(), value, value); + Node* add = graph()->NewNode(machine->Int32AddWithOverflow(), value, value, + graph()->start()); - Node* ovf = graph()->NewNode(common->Projection(1), add); + Node* ovf = graph()->NewNode(common->Projection(1), add, graph()->start()); Node* branch = graph()->NewNode(common->Branch(BranchHint::kFalse), ovf, graph()->start()); @@ -1986,7 +1991,7 @@ Node* WasmGraphBuilder::BuildChangeInt32ToTagged(Node* value) { graph()->NewNode(machine->ChangeInt32ToFloat64(), value), if_true); Node* if_false = graph()->NewNode(common->IfFalse(), branch); - Node* vfalse = graph()->NewNode(common->Projection(0), add); + Node* vfalse = graph()->NewNode(common->Projection(0), add, if_false); Node* merge = graph()->NewNode(common->Merge(2), if_true, if_false); Node* phi = graph()->NewNode(common->Phi(MachineRepresentation::kTagged, 2), @@ -2039,10 +2044,10 @@ Node* WasmGraphBuilder::BuildChangeFloat64ToTagged(Node* value) { if (machine->Is64()) { vsmi = BuildChangeInt32ToSmi(value32); } else { - Node* smi_tag = - graph()->NewNode(machine->Int32AddWithOverflow(), value32, value32); + Node* smi_tag = graph()->NewNode(machine->Int32AddWithOverflow(), value32, + value32, if_smi); - Node* check_ovf = graph()->NewNode(common->Projection(1), smi_tag); + Node* check_ovf = graph()->NewNode(common->Projection(1), smi_tag, if_smi); Node* branch_ovf = graph()->NewNode(common->Branch(BranchHint::kFalse), check_ovf, if_smi); @@ -2050,7 +2055,7 @@ Node* WasmGraphBuilder::BuildChangeFloat64ToTagged(Node* value) { if_box = graph()->NewNode(common->Merge(2), if_ovf, if_box); if_smi = graph()->NewNode(common->IfFalse(), branch_ovf); - vsmi = graph()->NewNode(common->Projection(0), smi_tag); + vsmi = graph()->NewNode(common->Projection(0), smi_tag, if_smi); } // Allocate the box for the {value}. @@ -2383,7 +2388,8 @@ void WasmGraphBuilder::BuildJSToWasmWrapper(Handle wasm_code, if (jsgraph()->machine()->Is32() && sig->return_count() > 0 && sig->GetReturn(0) == wasm::kAstI64) { // The return values comes as two values, we pick the low word. - retval = graph()->NewNode(jsgraph()->common()->Projection(0), retval); + retval = graph()->NewNode(jsgraph()->common()->Projection(0), retval, + graph()->start()); } Node* jsval = ToJS(retval, context, diff --git a/test/unittests/compiler/common-operator-unittest.cc b/test/unittests/compiler/common-operator-unittest.cc index 440359e3b5..52f99a5e12 100644 --- a/test/unittests/compiler/common-operator-unittest.cc +++ b/test/unittests/compiler/common-operator-unittest.cc @@ -392,6 +392,19 @@ TEST_F(CommonOperatorTest, FinishRegion) { EXPECT_EQ(1, op->ValueOutputCount()); } +TEST_F(CommonOperatorTest, Projection) { + TRACED_FORRANGE(size_t, index, 0, 3) { + const Operator* op = common()->Projection(index); + EXPECT_EQ(index, ProjectionIndexOf(op)); + EXPECT_EQ(1, op->ValueInputCount()); + EXPECT_EQ(1, op->ControlInputCount()); + EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op)); + EXPECT_EQ(0, op->ControlOutputCount()); + EXPECT_EQ(0, op->EffectOutputCount()); + EXPECT_EQ(1, op->ValueOutputCount()); + } +} + } // namespace compiler } // namespace internal } // namespace v8 diff --git a/test/unittests/compiler/machine-operator-reducer-unittest.cc b/test/unittests/compiler/machine-operator-reducer-unittest.cc index 39306b5218..05156edde1 100644 --- a/test/unittests/compiler/machine-operator-reducer-unittest.cc +++ b/test/unittests/compiler/machine-operator-reducer-unittest.cc @@ -1284,28 +1284,31 @@ TEST_F(MachineOperatorReducerTest, Int32AddWithInt32SubWithConstantZero) { TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithZero) { + Node* control = graph()->start(); Node* p0 = Parameter(0); { Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), - Int32Constant(0), p0); + Int32Constant(0), p0, control); - Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add)); + Reduction r = + Reduce(graph()->NewNode(common()->Projection(1), add, control)); ASSERT_TRUE(r.Changed()); EXPECT_THAT(r.replacement(), IsInt32Constant(0)); - r = Reduce(graph()->NewNode(common()->Projection(0), add)); + r = Reduce(graph()->NewNode(common()->Projection(0), add, control)); ASSERT_TRUE(r.Changed()); EXPECT_EQ(p0, r.replacement()); } { Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), p0, - Int32Constant(0)); + Int32Constant(0), control); - Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add)); + Reduction r = + Reduce(graph()->NewNode(common()->Projection(1), add, control)); ASSERT_TRUE(r.Changed()); EXPECT_THAT(r.replacement(), IsInt32Constant(0)); - r = Reduce(graph()->NewNode(common()->Projection(0), add)); + r = Reduce(graph()->NewNode(common()->Projection(0), add, control)); ASSERT_TRUE(r.Changed()); EXPECT_EQ(p0, r.replacement()); } @@ -1313,18 +1316,20 @@ TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithZero) { TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithConstant) { + Node* control = graph()->start(); TRACED_FOREACH(int32_t, x, kInt32Values) { TRACED_FOREACH(int32_t, y, kInt32Values) { int32_t z; Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), - Int32Constant(x), Int32Constant(y)); + Int32Constant(x), Int32Constant(y), control); - Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add)); + Reduction r = + Reduce(graph()->NewNode(common()->Projection(1), add, control)); ASSERT_TRUE(r.Changed()); EXPECT_THAT(r.replacement(), IsInt32Constant(base::bits::SignedAddOverflow32(x, y, &z))); - r = Reduce(graph()->NewNode(common()->Projection(0), add)); + r = Reduce(graph()->NewNode(common()->Projection(0), add, control)); ASSERT_TRUE(r.Changed()); EXPECT_THAT(r.replacement(), IsInt32Constant(z)); } @@ -1337,33 +1342,36 @@ TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithConstant) { TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithZero) { + Node* control = graph()->start(); Node* p0 = Parameter(0); - Node* add = - graph()->NewNode(machine()->Int32SubWithOverflow(), p0, Int32Constant(0)); + Node* add = graph()->NewNode(machine()->Int32SubWithOverflow(), p0, + Int32Constant(0), control); - Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add)); + Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add, control)); ASSERT_TRUE(r.Changed()); EXPECT_THAT(r.replacement(), IsInt32Constant(0)); - r = Reduce(graph()->NewNode(common()->Projection(0), add)); + r = Reduce(graph()->NewNode(common()->Projection(0), add, control)); ASSERT_TRUE(r.Changed()); EXPECT_EQ(p0, r.replacement()); } TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithConstant) { + Node* control = graph()->start(); TRACED_FOREACH(int32_t, x, kInt32Values) { TRACED_FOREACH(int32_t, y, kInt32Values) { int32_t z; Node* add = graph()->NewNode(machine()->Int32SubWithOverflow(), - Int32Constant(x), Int32Constant(y)); + Int32Constant(x), Int32Constant(y), control); - Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add)); + Reduction r = + Reduce(graph()->NewNode(common()->Projection(1), add, control)); ASSERT_TRUE(r.Changed()); EXPECT_THAT(r.replacement(), IsInt32Constant(base::bits::SignedSubOverflow32(x, y, &z))); - r = Reduce(graph()->NewNode(common()->Projection(0), add)); + r = Reduce(graph()->NewNode(common()->Projection(0), add, control)); ASSERT_TRUE(r.Changed()); EXPECT_THAT(r.replacement(), IsInt32Constant(z)); } diff --git a/test/unittests/compiler/machine-operator-unittest.cc b/test/unittests/compiler/machine-operator-unittest.cc index 0235d654c3..4367705a84 100644 --- a/test/unittests/compiler/machine-operator-unittest.cc +++ b/test/unittests/compiler/machine-operator-unittest.cc @@ -208,9 +208,7 @@ const PureOperator kPureOperators[] = { PURE(Word64Ror, 2, 0, 1), // -- PURE(Word64Equal, 2, 0, 1), // -- PURE(Int32Add, 2, 0, 1), // -- - PURE(Int32AddWithOverflow, 2, 0, 2), // -- PURE(Int32Sub, 2, 0, 1), // -- - PURE(Int32SubWithOverflow, 2, 0, 2), // -- PURE(Int32Mul, 2, 0, 1), // -- PURE(Int32MulHigh, 2, 0, 1), // -- PURE(Int32Div, 2, 1, 1), // --