diff --git a/src/compiler/effect-control-linearizer.cc b/src/compiler/effect-control-linearizer.cc index d625a753ad..3fcaa5dd95 100644 --- a/src/compiler/effect-control-linearizer.cc +++ b/src/compiler/effect-control-linearizer.cc @@ -667,6 +667,10 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node, case IrOpcode::kCheckedFloat64ToInt32: state = LowerCheckedFloat64ToInt32(node, frame_state, *effect, *control); break; + case IrOpcode::kCheckedTaggedSignedToInt32: + state = + LowerCheckedTaggedSignedToInt32(node, frame_state, *effect, *control); + break; case IrOpcode::kCheckedTaggedToInt32: state = LowerCheckedTaggedToInt32(node, frame_state, *effect, *control); break; @@ -1578,6 +1582,22 @@ EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node, return BuildCheckedFloat64ToInt32(value, frame_state, effect, control); } +EffectControlLinearizer::ValueEffectControl +EffectControlLinearizer::LowerCheckedTaggedSignedToInt32(Node* node, + Node* frame_state, + Node* effect, + Node* control) { + Node* value = node->InputAt(0); + + Node* check = ObjectIsSmi(value); + control = effect = + graph()->NewNode(common()->DeoptimizeUnless(DeoptimizeReason::kNotASmi), + check, frame_state, effect, control); + value = ChangeSmiToInt32(value); + + return ValueEffectControl(value, effect, control); +} + EffectControlLinearizer::ValueEffectControl EffectControlLinearizer::LowerCheckedTaggedToInt32(Node* node, Node* frame_state, diff --git a/src/compiler/effect-control-linearizer.h b/src/compiler/effect-control-linearizer.h index d4fb4a6898..4543cf0080 100644 --- a/src/compiler/effect-control-linearizer.h +++ b/src/compiler/effect-control-linearizer.h @@ -93,6 +93,10 @@ class EffectControlLinearizer { Node* effect, Node* control); ValueEffectControl LowerCheckedFloat64ToInt32(Node* node, Node* frame_state, Node* effect, Node* control); + ValueEffectControl LowerCheckedTaggedSignedToInt32(Node* node, + Node* frame_state, + Node* effect, + Node* control); ValueEffectControl LowerCheckedTaggedToInt32(Node* node, Node* frame_state, Node* effect, Node* control); ValueEffectControl LowerCheckedTaggedToFloat64(Node* node, Node* frame_state, diff --git a/src/compiler/opcodes.h b/src/compiler/opcodes.h index 8ba5d74ffa..b0529436f1 100644 --- a/src/compiler/opcodes.h +++ b/src/compiler/opcodes.h @@ -192,6 +192,7 @@ V(CheckedInt32Mul) \ V(CheckedUint32ToInt32) \ V(CheckedFloat64ToInt32) \ + V(CheckedTaggedSignedToInt32) \ V(CheckedTaggedToInt32) \ V(CheckedTruncateTaggedToWord32) \ V(CheckedTaggedToFloat64) diff --git a/src/compiler/redundancy-elimination.cc b/src/compiler/redundancy-elimination.cc index cf7dd4ee17..c671fc23b8 100644 --- a/src/compiler/redundancy-elimination.cc +++ b/src/compiler/redundancy-elimination.cc @@ -32,6 +32,7 @@ Reduction RedundancyElimination::Reduce(Node* node) { case IrOpcode::kCheckedInt32Mod: case IrOpcode::kCheckedInt32Mul: case IrOpcode::kCheckedTaggedToFloat64: + case IrOpcode::kCheckedTaggedSignedToInt32: case IrOpcode::kCheckedTaggedToInt32: case IrOpcode::kCheckedUint32ToInt32: return ReduceCheckNode(node); diff --git a/src/compiler/representation-change.cc b/src/compiler/representation-change.cc index 049ddfa05f..fcd616db0a 100644 --- a/src/compiler/representation-change.cc +++ b/src/compiler/representation-change.cc @@ -400,7 +400,8 @@ Node* RepresentationChanger::GetWord32RepresentationFor( case IrOpcode::kFloat32Constant: { float const fv = OpParameter(node); if (use_info.type_check() == TypeCheckKind::kNone || - (use_info.type_check() == TypeCheckKind::kSigned32 && + ((use_info.type_check() == TypeCheckKind::kSignedSmall || + use_info.type_check() == TypeCheckKind::kSigned32) && IsInt32Double(fv))) { return MakeTruncatedInt32Constant(fv); } @@ -410,7 +411,8 @@ Node* RepresentationChanger::GetWord32RepresentationFor( case IrOpcode::kFloat64Constant: { double const fv = OpParameter(node); if (use_info.type_check() == TypeCheckKind::kNone || - (use_info.type_check() == TypeCheckKind::kSigned32 && + ((use_info.type_check() == TypeCheckKind::kSignedSmall || + use_info.type_check() == TypeCheckKind::kSigned32) && IsInt32Double(fv))) { return MakeTruncatedInt32Constant(fv); } @@ -435,7 +437,8 @@ Node* RepresentationChanger::GetWord32RepresentationFor( op = machine()->ChangeFloat64ToInt32(); } else if (use_info.truncation().IsUsedAsWord32()) { op = machine()->TruncateFloat64ToWord32(); - } else if (use_info.type_check() == TypeCheckKind::kSigned32) { + } else if (use_info.type_check() == TypeCheckKind::kSignedSmall || + use_info.type_check() == TypeCheckKind::kSigned32) { op = simplified()->CheckedFloat64ToInt32(); } } else if (output_rep == MachineRepresentation::kFloat32) { @@ -446,7 +449,8 @@ Node* RepresentationChanger::GetWord32RepresentationFor( op = machine()->ChangeFloat64ToInt32(); } else if (use_info.truncation().IsUsedAsWord32()) { op = machine()->TruncateFloat64ToWord32(); - } else if (use_info.type_check() == TypeCheckKind::kSigned32) { + } else if (use_info.type_check() == TypeCheckKind::kSignedSmall || + use_info.type_check() == TypeCheckKind::kSigned32) { op = simplified()->CheckedFloat64ToInt32(); } } else if (output_rep == MachineRepresentation::kTagged) { @@ -462,13 +466,16 @@ Node* RepresentationChanger::GetWord32RepresentationFor( } else { op = simplified()->TruncateTaggedToWord32(); } + } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) { + op = simplified()->CheckedTaggedSignedToInt32(); } else if (use_info.type_check() == TypeCheckKind::kSigned32) { op = simplified()->CheckedTaggedToInt32(); } } else if (output_rep == MachineRepresentation::kWord32) { // Only the checked case should get here, the non-checked case is // handled in GetRepresentationFor. - if (use_info.type_check() == TypeCheckKind::kSigned32) { + if (use_info.type_check() == TypeCheckKind::kSignedSmall || + use_info.type_check() == TypeCheckKind::kSigned32) { if (output_type->Is(Type::Signed32())) { return node; } else if (output_type->Is(Type::Unsigned32())) { @@ -481,7 +488,8 @@ Node* RepresentationChanger::GetWord32RepresentationFor( } else if (output_rep == MachineRepresentation::kWord8 || output_rep == MachineRepresentation::kWord16) { DCHECK(use_info.representation() == MachineRepresentation::kWord32); - DCHECK(use_info.type_check() == TypeCheckKind::kSigned32); + DCHECK(use_info.type_check() == TypeCheckKind::kSignedSmall || + use_info.type_check() == TypeCheckKind::kSigned32); return node; } diff --git a/src/compiler/representation-change.h b/src/compiler/representation-change.h index a9fc283c7e..80d5a73bd9 100644 --- a/src/compiler/representation-change.h +++ b/src/compiler/representation-change.h @@ -74,12 +74,19 @@ class Truncation final { static bool LessGeneral(TruncationKind rep1, TruncationKind rep2); }; -enum class TypeCheckKind : uint8_t { kNone, kSigned32, kNumberOrOddball }; +enum class TypeCheckKind : uint8_t { + kNone, + kSignedSmall, + kSigned32, + kNumberOrOddball +}; inline std::ostream& operator<<(std::ostream& os, TypeCheckKind type_check) { switch (type_check) { case TypeCheckKind::kNone: return os << "None"; + case TypeCheckKind::kSignedSmall: + return os << "SignedSmall"; case TypeCheckKind::kSigned32: return os << "Signed32"; case TypeCheckKind::kNumberOrOddball: @@ -131,6 +138,10 @@ class UseInfo { } // Possibly deoptimizing conversions. + static UseInfo CheckedSignedSmallAsWord32() { + return UseInfo(MachineRepresentation::kWord32, Truncation::Any(), + TypeCheckKind::kSignedSmall); + } static UseInfo CheckedSigned32AsWord32() { return UseInfo(MachineRepresentation::kWord32, Truncation::Any(), TypeCheckKind::kSigned32); diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc index bf002fa522..a277388df2 100644 --- a/src/compiler/simplified-lowering.cc +++ b/src/compiler/simplified-lowering.cc @@ -87,6 +87,23 @@ MachineRepresentation MachineRepresentationFromArrayType( return MachineRepresentation::kNone; } +UseInfo CheckedUseInfoAsWord32FromHint(BinaryOperationHints::Hint hint) { + switch (hint) { + case BinaryOperationHints::kSignedSmall: + return UseInfo::CheckedSignedSmallAsWord32(); + case BinaryOperationHints::kSigned32: + return UseInfo::CheckedSigned32AsWord32(); + case BinaryOperationHints::kNumberOrOddball: + return UseInfo::CheckedNumberOrOddballAsWord32(); + case BinaryOperationHints::kNone: + case BinaryOperationHints::kString: + case BinaryOperationHints::kAny: + break; + } + UNREACHABLE(); + return UseInfo::None(); +} + UseInfo TruncatingUseInfoFromRepresentation(MachineRepresentation rep) { switch (rep) { case MachineRepresentation::kTagged: @@ -742,14 +759,8 @@ class RepresentationSelector { MachineRepresentation::kWord32); } BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op()); - if (hint == BinaryOperationHints::kSignedSmall || - hint == BinaryOperationHints::kSigned32) { - return VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), - MachineRepresentation::kWord32); - } - DCHECK_EQ(BinaryOperationHints::kNumberOrOddball, hint); - VisitBinop(node, UseInfo::CheckedNumberOrOddballAsWord32(), - MachineRepresentation::kWord32, Type::Signed32()); + return VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), + MachineRepresentation::kWord32); } // Helper for unops of the I -> O variety. @@ -1124,7 +1135,7 @@ class RepresentationSelector { if (hint == BinaryOperationHints::kSignedSmall || hint == BinaryOperationHints::kSigned32) { - VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), + VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), MachineRepresentation::kWord32, Type::Signed32()); if (lower()) ChangeToInt32OverflowOp(node); return; @@ -1412,7 +1423,7 @@ class RepresentationSelector { if (hint == BinaryOperationHints::kSignedSmall || hint == BinaryOperationHints::kSigned32) { - VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), + VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), MachineRepresentation::kWord32, Type::Signed32()); if (lower()) { LowerToCheckedInt32Mul(node, truncation, input0_type, input1_type); @@ -1508,11 +1519,11 @@ class RepresentationSelector { hint == BinaryOperationHints::kSigned32) { // If the result is truncated, we only need to check the inputs. if (truncation.IsUsedAsWord32()) { - VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), + VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), MachineRepresentation::kWord32); if (lower()) DeferReplacement(node, lowering->Int32Div(node)); } else { - VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), + VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), MachineRepresentation::kWord32, Type::Signed32()); if (lower()) ChangeToInt32OverflowOp(node); } @@ -1616,11 +1627,11 @@ class RepresentationSelector { hint == BinaryOperationHints::kSigned32) { // If the result is truncated, we only need to check the inputs. if (truncation.IsUsedAsWord32()) { - VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), + VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), MachineRepresentation::kWord32); if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); } else { - VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), + VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), MachineRepresentation::kWord32, Type::Signed32()); if (lower()) ChangeToInt32OverflowOp(node); } @@ -1747,9 +1758,7 @@ class RepresentationSelector { } BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op()); Type* rhs_type = GetUpperBound(node->InputAt(1)); - VisitBinop(node, hint == BinaryOperationHints::kNumberOrOddball - ? UseInfo::CheckedNumberOrOddballAsWord32() - : UseInfo::CheckedSigned32AsWord32(), + VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), MachineRepresentation::kWord32, Type::Signed32()); if (lower()) { lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type); @@ -1785,9 +1794,7 @@ class RepresentationSelector { } BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op()); Type* rhs_type = GetUpperBound(node->InputAt(1)); - VisitBinop(node, hint == BinaryOperationHints::kNumberOrOddball - ? UseInfo::CheckedNumberOrOddballAsWord32() - : UseInfo::CheckedSigned32AsWord32(), + VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), MachineRepresentation::kWord32, Type::Signed32()); if (lower()) { lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type); @@ -1823,9 +1830,7 @@ class RepresentationSelector { } BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op()); Type* rhs_type = GetUpperBound(node->InputAt(1)); - VisitBinop(node, hint == BinaryOperationHints::kNumberOrOddball - ? UseInfo::CheckedNumberOrOddballAsWord32() - : UseInfo::CheckedSigned32AsWord32(), + VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), MachineRepresentation::kWord32, Type::Unsigned32()); if (lower()) { lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type); @@ -2141,8 +2146,7 @@ class RepresentationSelector { } case IrOpcode::kCheckTaggedSigned: { if (SmiValuesAre32Bits() && truncation.IsUsedAsWord32()) { - // TODO(jarin,bmeurer): Add CheckedSignedSmallAsWord32? - VisitUnop(node, UseInfo::CheckedSigned32AsWord32(), + VisitUnop(node, UseInfo::CheckedSignedSmallAsWord32(), MachineRepresentation::kWord32); if (lower()) DeferReplacement(node, node->InputAt(0)); } else { diff --git a/src/compiler/simplified-operator.cc b/src/compiler/simplified-operator.cc index 945737cd55..53d1f9ae25 100644 --- a/src/compiler/simplified-operator.cc +++ b/src/compiler/simplified-operator.cc @@ -381,23 +381,24 @@ CompareOperationHints::Hint CompareOperationHintOf(const Operator* op) { V(SpeculativeNumberBitwiseOr) \ V(SpeculativeNumberBitwiseXor) -#define CHECKED_OP_LIST(V) \ - V(CheckBounds, 2, 1) \ - V(CheckIf, 1, 0) \ - V(CheckNumber, 1, 1) \ - V(CheckString, 1, 1) \ - V(CheckTaggedPointer, 1, 1) \ - V(CheckTaggedSigned, 1, 1) \ - V(CheckedInt32Add, 2, 1) \ - V(CheckedInt32Sub, 2, 1) \ - V(CheckedInt32Div, 2, 1) \ - V(CheckedInt32Mod, 2, 1) \ - V(CheckedUint32Div, 2, 1) \ - V(CheckedUint32Mod, 2, 1) \ - V(CheckedUint32ToInt32, 1, 1) \ - V(CheckedFloat64ToInt32, 1, 1) \ - V(CheckedTaggedToInt32, 1, 1) \ - V(CheckedTaggedToFloat64, 1, 1) \ +#define CHECKED_OP_LIST(V) \ + V(CheckBounds, 2, 1) \ + V(CheckIf, 1, 0) \ + V(CheckNumber, 1, 1) \ + V(CheckString, 1, 1) \ + V(CheckTaggedPointer, 1, 1) \ + V(CheckTaggedSigned, 1, 1) \ + V(CheckedInt32Add, 2, 1) \ + V(CheckedInt32Sub, 2, 1) \ + V(CheckedInt32Div, 2, 1) \ + V(CheckedInt32Mod, 2, 1) \ + V(CheckedUint32Div, 2, 1) \ + V(CheckedUint32Mod, 2, 1) \ + V(CheckedUint32ToInt32, 1, 1) \ + V(CheckedFloat64ToInt32, 1, 1) \ + V(CheckedTaggedSignedToInt32, 1, 1) \ + V(CheckedTaggedToInt32, 1, 1) \ + V(CheckedTaggedToFloat64, 1, 1) \ V(CheckedTruncateTaggedToWord32, 1, 1) struct SimplifiedOperatorGlobalCache final { diff --git a/src/compiler/simplified-operator.h b/src/compiler/simplified-operator.h index 310389704e..02b4b4a463 100644 --- a/src/compiler/simplified-operator.h +++ b/src/compiler/simplified-operator.h @@ -296,6 +296,7 @@ class SimplifiedOperatorBuilder final : public ZoneObject { const Operator* CheckedInt32Mul(CheckForMinusZeroMode); const Operator* CheckedUint32ToInt32(); const Operator* CheckedFloat64ToInt32(); + const Operator* CheckedTaggedSignedToInt32(); const Operator* CheckedTaggedToInt32(); const Operator* CheckedTaggedToFloat64(); const Operator* CheckedTruncateTaggedToWord32(); diff --git a/src/compiler/verifier.cc b/src/compiler/verifier.cc index f7d22ff188..cb8a12035a 100644 --- a/src/compiler/verifier.cc +++ b/src/compiler/verifier.cc @@ -1018,6 +1018,7 @@ void Verifier::Visitor::Check(Node* node) { case IrOpcode::kCheckedInt32Mul: case IrOpcode::kCheckedUint32ToInt32: case IrOpcode::kCheckedFloat64ToInt32: + case IrOpcode::kCheckedTaggedSignedToInt32: case IrOpcode::kCheckedTaggedToInt32: case IrOpcode::kCheckedTaggedToFloat64: case IrOpcode::kCheckedTruncateTaggedToWord32: diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status index 5d53b805f4..41c30c18d4 100644 --- a/test/cctest/cctest.status +++ b/test/cctest/cctest.status @@ -103,6 +103,7 @@ 'test-heap/ObjectsInOptimizedCodeAreWeak': [PASS, NO_VARIANTS], # TurboFan cpu profiler result is different. + 'test-cpu-profiler/CollectDeoptEvents': [PASS, NO_VARIANTS], 'test-cpu-profiler/DeoptAtFirstLevelInlinedSource': [PASS, NO_VARIANTS], 'test-cpu-profiler/DeoptAtSecondLevelInlinedSource': [PASS, NO_VARIANTS], @@ -147,7 +148,6 @@ 'test-heap/ResetSharedFunctionInfoCountersDuringMarkSweep': [PASS, NO_IGNITION], # BUG(4680): Missing type feedback makes optimistic optimizations fail. - 'test-cpu-profiler/CollectDeoptEvents': [PASS, NO_IGNITION], 'test-cpu-profiler/DeoptUntrackedFunction': [PASS, NO_IGNITION], # BUG(4680): Ignition doesn't support allocation sites currently.