[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}
This commit is contained in:
parent
d48170dbf5
commit
cf4b9307ad
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user