[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:
bmeurer 2016-08-03 05:45:37 -07:00 committed by Commit bot
parent d48170dbf5
commit cf4b9307ad
11 changed files with 102 additions and 50 deletions

View File

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

View File

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

View File

@ -192,6 +192,7 @@
V(CheckedInt32Mul) \
V(CheckedUint32ToInt32) \
V(CheckedFloat64ToInt32) \
V(CheckedTaggedSignedToInt32) \
V(CheckedTaggedToInt32) \
V(CheckedTruncateTaggedToWord32) \
V(CheckedTaggedToFloat64)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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