[turbofan] Properly support Number feedback for binary operators.
Previously Ignition would collect precise Number feedback for binary operators, but TurboFan would just ignore that and treat it the same as NumberOrOddball. That however generates a lot of unnecessary code, plus it defeats redundancy elimination if the same input is also used by compare operations, which do properly distinguish feedback Number and NumberOrOddball. This CL adds the missing bits to connect the existing functionality properly, i.e. adding the missing BinaryOperationHint and using the NumberOperationHint::kNumber in the representation selection for tagged inputs. R=jarin@chromium.org Review-Url: https://codereview.chromium.org/2923543003 Cr-Commit-Position: refs/heads/master@{#45732}
This commit is contained in:
parent
bdf0ea99df
commit
8a15026270
@ -1811,6 +1811,7 @@ Node* EffectControlLinearizer::LowerTruncateTaggedToWord32(Node* node) {
|
||||
|
||||
Node* EffectControlLinearizer::LowerCheckedTruncateTaggedToWord32(
|
||||
Node* node, Node* frame_state) {
|
||||
CheckTaggedInputMode mode = CheckTaggedInputModeOf(node->op());
|
||||
Node* value = node->InputAt(0);
|
||||
|
||||
auto if_not_smi = __ MakeLabel<1>();
|
||||
@ -1824,8 +1825,8 @@ Node* EffectControlLinearizer::LowerCheckedTruncateTaggedToWord32(
|
||||
// Otherwise, check that it's a heap number or oddball and truncate the value
|
||||
// to int32.
|
||||
__ Bind(&if_not_smi);
|
||||
Node* number = BuildCheckedHeapNumberOrOddballToFloat64(
|
||||
CheckTaggedInputMode::kNumberOrOddball, value, frame_state);
|
||||
Node* number =
|
||||
BuildCheckedHeapNumberOrOddballToFloat64(mode, value, frame_state);
|
||||
number = __ TruncateFloat64ToWord32(number);
|
||||
__ Goto(&done, number);
|
||||
|
||||
|
@ -643,6 +643,7 @@ struct JSOperatorGlobalCache final {
|
||||
Name##Operator<BinaryOperationHint::kSignedSmall> \
|
||||
k##Name##SignedSmallOperator; \
|
||||
Name##Operator<BinaryOperationHint::kSigned32> k##Name##Signed32Operator; \
|
||||
Name##Operator<BinaryOperationHint::kNumber> k##Name##NumberOperator; \
|
||||
Name##Operator<BinaryOperationHint::kNumberOrOddball> \
|
||||
k##Name##NumberOrOddballOperator; \
|
||||
Name##Operator<BinaryOperationHint::kString> k##Name##StringOperator; \
|
||||
@ -696,6 +697,8 @@ CACHED_OP_LIST(CACHED_OP)
|
||||
return &cache_.k##Name##SignedSmallOperator; \
|
||||
case BinaryOperationHint::kSigned32: \
|
||||
return &cache_.k##Name##Signed32Operator; \
|
||||
case BinaryOperationHint::kNumber: \
|
||||
return &cache_.k##Name##NumberOperator; \
|
||||
case BinaryOperationHint::kNumberOrOddball: \
|
||||
return &cache_.k##Name##NumberOrOddballOperator; \
|
||||
case BinaryOperationHint::kString: \
|
||||
|
@ -25,6 +25,9 @@ bool BinaryOperationHintToNumberOperationHint(
|
||||
case BinaryOperationHint::kSigned32:
|
||||
*number_hint = NumberOperationHint::kSigned32;
|
||||
return true;
|
||||
case BinaryOperationHint::kNumber:
|
||||
*number_hint = NumberOperationHint::kNumber;
|
||||
return true;
|
||||
case BinaryOperationHint::kNumberOrOddball:
|
||||
*number_hint = NumberOperationHint::kNumberOrOddball;
|
||||
return true;
|
||||
|
@ -533,7 +533,8 @@ JSTypedLowering::JSTypedLowering(Editor* editor,
|
||||
Reduction JSTypedLowering::ReduceSpeculativeNumberAdd(Node* node) {
|
||||
JSBinopReduction r(this, node);
|
||||
NumberOperationHint hint = NumberOperationHintOf(node->op());
|
||||
if (hint == NumberOperationHint::kNumberOrOddball &&
|
||||
if ((hint == NumberOperationHint::kNumber ||
|
||||
hint == NumberOperationHint::kNumberOrOddball) &&
|
||||
r.BothInputsAre(Type::PlainPrimitive()) &&
|
||||
r.NeitherInputCanBe(Type::StringOrReceiver())) {
|
||||
// SpeculativeNumberAdd(x:-string, y:-string) =>
|
||||
@ -621,7 +622,8 @@ Reduction JSTypedLowering::ReduceNumberBinop(Node* node) {
|
||||
Reduction JSTypedLowering::ReduceSpeculativeNumberBinop(Node* node) {
|
||||
JSBinopReduction r(this, node);
|
||||
NumberOperationHint hint = NumberOperationHintOf(node->op());
|
||||
if (hint == NumberOperationHint::kNumberOrOddball &&
|
||||
if ((hint == NumberOperationHint::kNumber ||
|
||||
hint == NumberOperationHint::kNumberOrOddball) &&
|
||||
r.BothInputsAre(Type::NumberOrOddball())) {
|
||||
r.ConvertInputsToNumber();
|
||||
return r.ChangeToPureOperator(r.NumberOpFromSpeculativeNumberOp(),
|
||||
|
@ -674,22 +674,11 @@ Node* RepresentationChanger::GetWord32RepresentationFor(
|
||||
return TypeError(node, output_rep, output_type,
|
||||
MachineRepresentation::kWord32);
|
||||
}
|
||||
} else if (output_rep == MachineRepresentation::kTaggedSigned) {
|
||||
if (output_type->Is(Type::Signed32())) {
|
||||
} else if (IsAnyTagged(output_rep)) {
|
||||
if (output_rep == MachineRepresentation::kTaggedSigned &&
|
||||
output_type->Is(Type::SignedSmall())) {
|
||||
op = simplified()->ChangeTaggedSignedToInt32();
|
||||
} else if (use_info.truncation().IsUsedAsWord32()) {
|
||||
if (use_info.type_check() != TypeCheckKind::kNone) {
|
||||
op = simplified()->CheckedTruncateTaggedToWord32();
|
||||
} else {
|
||||
op = simplified()->TruncateTaggedToWord32();
|
||||
}
|
||||
} else {
|
||||
return TypeError(node, output_rep, output_type,
|
||||
MachineRepresentation::kWord32);
|
||||
}
|
||||
} else if (output_rep == MachineRepresentation::kTagged ||
|
||||
output_rep == MachineRepresentation::kTaggedPointer) {
|
||||
if (output_type->Is(Type::Signed32())) {
|
||||
} else if (output_type->Is(Type::Signed32())) {
|
||||
op = simplified()->ChangeTaggedToInt32();
|
||||
} else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
|
||||
op = simplified()->CheckedTaggedSignedToInt32();
|
||||
@ -703,8 +692,12 @@ Node* RepresentationChanger::GetWord32RepresentationFor(
|
||||
} else if (use_info.truncation().IsUsedAsWord32()) {
|
||||
if (output_type->Is(Type::NumberOrOddball())) {
|
||||
op = simplified()->TruncateTaggedToWord32();
|
||||
} else if (use_info.type_check() != TypeCheckKind::kNone) {
|
||||
op = simplified()->CheckedTruncateTaggedToWord32();
|
||||
} else if (use_info.type_check() == TypeCheckKind::kNumber) {
|
||||
op = simplified()->CheckedTruncateTaggedToWord32(
|
||||
CheckTaggedInputMode::kNumber);
|
||||
} else if (use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
|
||||
op = simplified()->CheckedTruncateTaggedToWord32(
|
||||
CheckTaggedInputMode::kNumberOrOddball);
|
||||
} else {
|
||||
return TypeError(node, output_rep, output_type,
|
||||
MachineRepresentation::kWord32);
|
||||
@ -726,8 +719,8 @@ Node* RepresentationChanger::GetWord32RepresentationFor(
|
||||
return TypeError(node, output_rep, output_type,
|
||||
MachineRepresentation::kWord32);
|
||||
}
|
||||
} else {
|
||||
DCHECK_EQ(TypeCheckKind::kNumberOrOddball, use_info.type_check());
|
||||
} else if (use_info.type_check() == TypeCheckKind::kNumber ||
|
||||
use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
|
||||
return node;
|
||||
}
|
||||
} else if (output_rep == MachineRepresentation::kWord8 ||
|
||||
|
@ -284,7 +284,8 @@ std::ostream& operator<<(std::ostream& os, CheckTaggedInputMode mode) {
|
||||
}
|
||||
|
||||
CheckTaggedInputMode CheckTaggedInputModeOf(const Operator* op) {
|
||||
DCHECK_EQ(IrOpcode::kCheckedTaggedToFloat64, op->opcode());
|
||||
DCHECK(op->opcode() == IrOpcode::kCheckedTaggedToFloat64 ||
|
||||
op->opcode() == IrOpcode::kCheckedTruncateTaggedToWord32);
|
||||
return OpParameter<CheckTaggedInputMode>(op);
|
||||
}
|
||||
|
||||
@ -514,32 +515,31 @@ UnicodeEncoding UnicodeEncodingOf(const Operator* op) {
|
||||
V(SpeculativeNumberLessThan) \
|
||||
V(SpeculativeNumberLessThanOrEqual)
|
||||
|
||||
#define CHECKED_OP_LIST(V) \
|
||||
V(CheckBounds, 2, 1) \
|
||||
V(CheckHeapObject, 1, 1) \
|
||||
V(CheckIf, 1, 0) \
|
||||
V(CheckInternalizedString, 1, 1) \
|
||||
V(CheckNumber, 1, 1) \
|
||||
V(CheckReceiver, 1, 1) \
|
||||
V(CheckSmi, 1, 1) \
|
||||
V(CheckString, 1, 1) \
|
||||
V(CheckSeqString, 1, 1) \
|
||||
V(CheckSymbol, 1, 1) \
|
||||
V(CheckTaggedHole, 1, 0) \
|
||||
V(CheckNotTaggedHole, 1, 0) \
|
||||
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(CheckedUint32ToTaggedSigned, 1, 1) \
|
||||
V(CheckedInt32ToTaggedSigned, 1, 1) \
|
||||
V(CheckedTaggedSignedToInt32, 1, 1) \
|
||||
V(CheckedTaggedToTaggedSigned, 1, 1) \
|
||||
V(CheckedTaggedToTaggedPointer, 1, 1) \
|
||||
V(CheckedTruncateTaggedToWord32, 1, 1)
|
||||
#define CHECKED_OP_LIST(V) \
|
||||
V(CheckBounds, 2, 1) \
|
||||
V(CheckHeapObject, 1, 1) \
|
||||
V(CheckIf, 1, 0) \
|
||||
V(CheckInternalizedString, 1, 1) \
|
||||
V(CheckNumber, 1, 1) \
|
||||
V(CheckReceiver, 1, 1) \
|
||||
V(CheckSmi, 1, 1) \
|
||||
V(CheckString, 1, 1) \
|
||||
V(CheckSeqString, 1, 1) \
|
||||
V(CheckSymbol, 1, 1) \
|
||||
V(CheckTaggedHole, 1, 0) \
|
||||
V(CheckNotTaggedHole, 1, 0) \
|
||||
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(CheckedUint32ToTaggedSigned, 1, 1) \
|
||||
V(CheckedInt32ToTaggedSigned, 1, 1) \
|
||||
V(CheckedTaggedSignedToInt32, 1, 1) \
|
||||
V(CheckedTaggedToTaggedSigned, 1, 1) \
|
||||
V(CheckedTaggedToTaggedPointer, 1, 1)
|
||||
|
||||
struct SimplifiedOperatorGlobalCache final {
|
||||
#define PURE(Name, properties, value_input_count, control_input_count) \
|
||||
@ -666,6 +666,20 @@ struct SimplifiedOperatorGlobalCache final {
|
||||
CheckedTaggedToFloat64Operator<CheckTaggedInputMode::kNumberOrOddball>
|
||||
kCheckedTaggedToFloat64NumberOrOddballOperator;
|
||||
|
||||
template <CheckTaggedInputMode kMode>
|
||||
struct CheckedTruncateTaggedToWord32Operator final
|
||||
: public Operator1<CheckTaggedInputMode> {
|
||||
CheckedTruncateTaggedToWord32Operator()
|
||||
: Operator1<CheckTaggedInputMode>(
|
||||
IrOpcode::kCheckedTruncateTaggedToWord32,
|
||||
Operator::kFoldable | Operator::kNoThrow,
|
||||
"CheckedTruncateTaggedToWord32", 1, 1, 1, 1, 1, 0, kMode) {}
|
||||
};
|
||||
CheckedTruncateTaggedToWord32Operator<CheckTaggedInputMode::kNumber>
|
||||
kCheckedTruncateTaggedToWord32NumberOperator;
|
||||
CheckedTruncateTaggedToWord32Operator<CheckTaggedInputMode::kNumberOrOddball>
|
||||
kCheckedTruncateTaggedToWord32NumberOrOddballOperator;
|
||||
|
||||
template <CheckFloat64HoleMode kMode>
|
||||
struct CheckFloat64HoleNaNOperator final
|
||||
: public Operator1<CheckFloat64HoleMode> {
|
||||
@ -822,6 +836,17 @@ const Operator* SimplifiedOperatorBuilder::CheckedTaggedToFloat64(
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
const Operator* SimplifiedOperatorBuilder::CheckedTruncateTaggedToWord32(
|
||||
CheckTaggedInputMode mode) {
|
||||
switch (mode) {
|
||||
case CheckTaggedInputMode::kNumber:
|
||||
return &cache_.kCheckedTruncateTaggedToWord32NumberOperator;
|
||||
case CheckTaggedInputMode::kNumberOrOddball:
|
||||
return &cache_.kCheckedTruncateTaggedToWord32NumberOrOddballOperator;
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
const Operator* SimplifiedOperatorBuilder::CheckMaps(CheckMapsFlags flags,
|
||||
ZoneHandleSet<Map> maps) {
|
||||
CheckMapsParameters const parameters(flags, maps);
|
||||
|
@ -435,7 +435,7 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
|
||||
const Operator* CheckedTaggedToFloat64(CheckTaggedInputMode);
|
||||
const Operator* CheckedTaggedToTaggedSigned();
|
||||
const Operator* CheckedTaggedToTaggedPointer();
|
||||
const Operator* CheckedTruncateTaggedToWord32();
|
||||
const Operator* CheckedTruncateTaggedToWord32(CheckTaggedInputMode);
|
||||
|
||||
const Operator* CheckFloat64Hole(CheckFloat64HoleMode);
|
||||
const Operator* CheckTaggedHole();
|
||||
|
@ -147,6 +147,7 @@ BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback) {
|
||||
case BinaryOperationFeedback::kSignedSmall:
|
||||
return BinaryOperationHint::kSignedSmall;
|
||||
case BinaryOperationFeedback::kNumber:
|
||||
return BinaryOperationHint::kNumber;
|
||||
case BinaryOperationFeedback::kNumberOrOddball:
|
||||
return BinaryOperationHint::kNumberOrOddball;
|
||||
case BinaryOperationFeedback::kString:
|
||||
|
@ -15,6 +15,8 @@ std::ostream& operator<<(std::ostream& os, BinaryOperationHint hint) {
|
||||
return os << "SignedSmall";
|
||||
case BinaryOperationHint::kSigned32:
|
||||
return os << "Signed32";
|
||||
case BinaryOperationHint::kNumber:
|
||||
return os << "Number";
|
||||
case BinaryOperationHint::kNumberOrOddball:
|
||||
return os << "NumberOrOddball";
|
||||
case BinaryOperationHint::kString:
|
||||
|
@ -16,6 +16,7 @@ enum class BinaryOperationHint : uint8_t {
|
||||
kNone,
|
||||
kSignedSmall,
|
||||
kSigned32,
|
||||
kNumber,
|
||||
kNumberOrOddball,
|
||||
kString,
|
||||
kAny
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
foo(1.1, 0.1);
|
||||
foo(0.1, 1.1);
|
||||
foo(true, false);
|
||||
%OptimizeFunctionOnNextCall(foo);
|
||||
foo(undefined, 1.1);
|
||||
assertOptimized(foo);
|
||||
@ -33,6 +34,7 @@
|
||||
|
||||
foo(1.1, 0.1);
|
||||
foo(0.1, 1.1);
|
||||
foo(true, false);
|
||||
%OptimizeFunctionOnNextCall(foo);
|
||||
foo(undefined, 1.1);
|
||||
assertOptimized(foo);
|
||||
@ -57,6 +59,7 @@
|
||||
|
||||
foo(1.1, 0.1);
|
||||
foo(0.1, 1.1);
|
||||
foo(true, false);
|
||||
%OptimizeFunctionOnNextCall(foo);
|
||||
foo(undefined, 1.1);
|
||||
assertOptimized(foo);
|
||||
@ -81,6 +84,7 @@
|
||||
|
||||
foo(1.1, 0.1);
|
||||
foo(0.1, 1.1);
|
||||
foo(true, false);
|
||||
%OptimizeFunctionOnNextCall(foo);
|
||||
foo(undefined, 1.1);
|
||||
assertOptimized(foo);
|
||||
@ -105,6 +109,7 @@
|
||||
|
||||
foo(1.1, 0.1);
|
||||
foo(0.1, 1.1);
|
||||
foo(true, false);
|
||||
%OptimizeFunctionOnNextCall(foo);
|
||||
foo(undefined, 1.1);
|
||||
assertOptimized(foo);
|
||||
@ -129,6 +134,7 @@
|
||||
|
||||
foo(1.1, 0.1);
|
||||
foo(0.1, 1.1);
|
||||
foo(true, false);
|
||||
%OptimizeFunctionOnNextCall(foo);
|
||||
foo(undefined, 1.1);
|
||||
assertOptimized(foo);
|
||||
|
Loading…
Reference in New Issue
Block a user