Commit cf4b9307 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Consume SignedSmall feedback for number operations.

So far we treated SignedSmall and Signed32 feedback the same for number
operations. However it would be beneficial to generate (a lot) less code
if we only do a Smi check on the inputs instead of doing the full Smi +
HeapNumber + conversion check that we need to do for Signed32 feedback.

R=epertoso@chromium.org
BUG=v8:4583

Review-Url: https://codereview.chromium.org/2207893002
Cr-Commit-Position: refs/heads/master@{#38290}
parent d48170db
......@@ -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,
......
......@@ -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,
......
......@@ -192,6 +192,7 @@
V(CheckedInt32Mul) \
V(CheckedUint32ToInt32) \
V(CheckedFloat64ToInt32) \
V(CheckedTaggedSignedToInt32) \
V(CheckedTaggedToInt32) \
V(CheckedTruncateTaggedToWord32) \
V(CheckedTaggedToFloat64)
......
......@@ -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);
......
......@@ -400,7 +400,8 @@ Node* RepresentationChanger::GetWord32RepresentationFor(
case IrOpcode::kFloat32Constant: {
float const fv = OpParameter<float>(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<double>(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;
}
......
......@@ -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);
......
......@@ -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 {
......
......@@ -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 {
......
......@@ -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();
......
......@@ -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:
......
......@@ -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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment