Commit dfbb3db5 authored by Benedikt Meurer's avatar Benedikt Meurer

[turbofan] Improve representation selection for Smi checking.

Rename the high-level operators CheckTaggedSigned to CheckSmi and
CheckTaggedPointer to CheckHeapObject, to better match the naming
convention (i.e. ObjectIsSmi and CheckSmi, ObjectIsString and
CheckString, etc.).

For lowering CheckSmi, always report TaggedSigned representation
and let the RepresentationChanger come up with a reasonable conversion
from whatever input representation to TaggedSigned. This way we no
longer insert the useless ChangeSomethingToTagged and then Smi check
the result sequences, i.e. mostly reduces the amount of useless code
being generated. But we also observe a few performance improvements
on some crypto benchmarks.

This would enable us to avoid the Smi canonicalization when going from
Float64 to Tagged completely and thus match the representation selection
of Crankshaft in many areas (which might reduce the amount of
polymorphism until we fix our object model).

A follow-up CL will do the same for CheckHeapObject.

BUG=v8:5267
R=jarin@chromium.org

Review URL: https://codereview.chromium.org/2362173003 .

Cr-Commit-Position: refs/heads/master@{#39654}
parent 49be3192
......@@ -880,13 +880,21 @@ void CodeGenerator::AddTranslationForOperand(Translation* translation,
DCHECK(constant_object->IsSmi());
break;
case Constant::kFloat32:
DCHECK(type.representation() == MachineRepresentation::kFloat32 ||
CanBeTaggedPointer(type.representation()));
if (type.representation() == MachineRepresentation::kTaggedSigned) {
DCHECK(IsSmiDouble(constant.ToFloat32()));
} else {
DCHECK(type.representation() == MachineRepresentation::kFloat32 ||
CanBeTaggedPointer(type.representation()));
}
constant_object = isolate()->factory()->NewNumber(constant.ToFloat32());
break;
case Constant::kFloat64:
DCHECK(type.representation() == MachineRepresentation::kFloat64 ||
CanBeTaggedPointer(type.representation()));
if (type.representation() == MachineRepresentation::kTaggedSigned) {
DCHECK(IsSmiDouble(constant.ToFloat64()));
} else {
DCHECK(type.representation() == MachineRepresentation::kFloat64 ||
CanBeTaggedPointer(type.representation()));
}
constant_object = isolate()->factory()->NewNumber(constant.ToFloat64());
break;
case Constant::kHeapObject:
......
......@@ -636,11 +636,8 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kCheckIf:
state = LowerCheckIf(node, frame_state, *effect, *control);
break;
case IrOpcode::kCheckTaggedPointer:
state = LowerCheckTaggedPointer(node, frame_state, *effect, *control);
break;
case IrOpcode::kCheckTaggedSigned:
state = LowerCheckTaggedSigned(node, frame_state, *effect, *control);
case IrOpcode::kCheckHeapObject:
state = LowerCheckHeapObject(node, frame_state, *effect, *control);
break;
case IrOpcode::kCheckedInt32Add:
state = LowerCheckedInt32Add(node, frame_state, *effect, *control);
......@@ -663,9 +660,17 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kCheckedInt32Mul:
state = LowerCheckedInt32Mul(node, frame_state, *effect, *control);
break;
case IrOpcode::kCheckedInt32ToTaggedSigned:
state =
LowerCheckedInt32ToTaggedSigned(node, frame_state, *effect, *control);
break;
case IrOpcode::kCheckedUint32ToInt32:
state = LowerCheckedUint32ToInt32(node, frame_state, *effect, *control);
break;
case IrOpcode::kCheckedUint32ToTaggedSigned:
state = LowerCheckedUint32ToTaggedSigned(node, frame_state, *effect,
*control);
break;
case IrOpcode::kCheckedFloat64ToInt32:
state = LowerCheckedFloat64ToInt32(node, frame_state, *effect, *control);
break;
......@@ -679,6 +684,10 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kCheckedTaggedToFloat64:
state = LowerCheckedTaggedToFloat64(node, frame_state, *effect, *control);
break;
case IrOpcode::kCheckedTaggedToTaggedSigned:
state = LowerCheckedTaggedToTaggedSigned(node, frame_state, *effect,
*control);
break;
case IrOpcode::kTruncateTaggedToWord32:
state = LowerTruncateTaggedToWord32(node, *effect, *control);
break;
......@@ -1320,8 +1329,8 @@ EffectControlLinearizer::LowerCheckIf(Node* node, Node* frame_state,
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckTaggedPointer(Node* node, Node* frame_state,
Node* effect, Node* control) {
EffectControlLinearizer::LowerCheckHeapObject(Node* node, Node* frame_state,
Node* effect, Node* control) {
Node* value = node->InputAt(0);
Node* check = ObjectIsSmi(value);
......@@ -1332,19 +1341,6 @@ EffectControlLinearizer::LowerCheckTaggedPointer(Node* node, Node* frame_state,
return ValueEffectControl(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckTaggedSigned(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);
return ValueEffectControl(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckedInt32Add(Node* node, Node* frame_state,
Node* effect, Node* control) {
......@@ -1670,6 +1666,27 @@ EffectControlLinearizer::LowerCheckedInt32Mul(Node* node, Node* frame_state,
return ValueEffectControl(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckedInt32ToTaggedSigned(Node* node,
Node* frame_state,
Node* effect,
Node* control) {
DCHECK(SmiValuesAre31Bits());
Node* value = node->InputAt(0);
Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), value, value,
control);
Node* check = graph()->NewNode(common()->Projection(1), add, control);
control = effect =
graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kOverflow),
check, frame_state, effect, control);
value = graph()->NewNode(common()->Projection(0), add, control);
return ValueEffectControl(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node,
Node* frame_state,
......@@ -1686,6 +1703,22 @@ EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node,
return ValueEffectControl(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckedUint32ToTaggedSigned(Node* node,
Node* frame_state,
Node* effect,
Node* control) {
Node* value = node->InputAt(0);
Node* check = graph()->NewNode(machine()->Uint32LessThanOrEqual(), value,
SmiMaxValueConstant());
control = effect = graph()->NewNode(
common()->DeoptimizeUnless(DeoptimizeReason::kLostPrecision), check,
frame_state, effect, control);
value = ChangeUint32ToSmi(value);
return ValueEffectControl(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::BuildCheckedFloat64ToInt32(CheckForMinusZeroMode mode,
Node* value,
......@@ -1890,6 +1923,21 @@ EffectControlLinearizer::LowerCheckedTaggedToFloat64(Node* node,
return ValueEffectControl(result, effect_phi, merge);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckedTaggedToTaggedSigned(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);
return ValueEffectControl(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerTruncateTaggedToWord32(Node* node, Node* effect,
Node* control) {
......
......@@ -71,10 +71,8 @@ class EffectControlLinearizer {
Node* effect, Node* control);
ValueEffectControl LowerCheckIf(Node* node, Node* frame_state, Node* effect,
Node* control);
ValueEffectControl LowerCheckTaggedPointer(Node* node, Node* frame_state,
Node* effect, Node* control);
ValueEffectControl LowerCheckTaggedSigned(Node* node, Node* frame_state,
Node* effect, Node* control);
ValueEffectControl LowerCheckHeapObject(Node* node, Node* frame_state,
Node* effect, Node* control);
ValueEffectControl LowerCheckedInt32Add(Node* node, Node* frame_state,
Node* effect, Node* control);
ValueEffectControl LowerCheckedInt32Sub(Node* node, Node* frame_state,
......@@ -89,8 +87,16 @@ class EffectControlLinearizer {
Node* effect, Node* control);
ValueEffectControl LowerCheckedInt32Mul(Node* node, Node* frame_state,
Node* effect, Node* control);
ValueEffectControl LowerCheckedInt32ToTaggedSigned(Node* node,
Node* frame_state,
Node* effect,
Node* control);
ValueEffectControl LowerCheckedUint32ToInt32(Node* node, Node* frame_state,
Node* effect, Node* control);
ValueEffectControl LowerCheckedUint32ToTaggedSigned(Node* node,
Node* frame_state,
Node* effect,
Node* control);
ValueEffectControl LowerCheckedFloat64ToInt32(Node* node, Node* frame_state,
Node* effect, Node* control);
ValueEffectControl LowerCheckedTaggedSignedToInt32(Node* node,
......@@ -101,6 +107,10 @@ class EffectControlLinearizer {
Node* effect, Node* control);
ValueEffectControl LowerCheckedTaggedToFloat64(Node* node, Node* frame_state,
Node* effect, Node* control);
ValueEffectControl LowerCheckedTaggedToTaggedSigned(Node* node,
Node* frame_state,
Node* effect,
Node* control);
ValueEffectControl LowerChangeTaggedToFloat64(Node* node, Node* effect,
Node* control);
ValueEffectControl LowerTruncateTaggedToBit(Node* node, Node* effect,
......
......@@ -275,8 +275,8 @@ Reduction JSBuiltinReducer::ReduceArrayPush(Node* node) {
// here is to learn on deopt, i.e. disable Array.prototype.push inlining
// for this function.
if (IsFastSmiElementsKind(receiver_map->elements_kind())) {
value = effect = graph()->NewNode(simplified()->CheckTaggedSigned(),
value, effect, control);
value = effect =
graph()->NewNode(simplified()->CheckSmi(), value, effect, control);
} else if (IsFastDoubleElementsKind(receiver_map->elements_kind())) {
value = effect =
graph()->NewNode(simplified()->CheckNumber(), value, effect, control);
......
......@@ -207,7 +207,7 @@ Reduction JSGlobalObjectSpecialization::ReduceJSStoreGlobal(Node* node) {
MachineRepresentation representation = MachineRepresentation::kTagged;
if (property_cell_value->IsHeapObject()) {
// Check that the {value} is a HeapObject.
value = effect = graph()->NewNode(simplified()->CheckTaggedPointer(),
value = effect = graph()->NewNode(simplified()->CheckHeapObject(),
value, effect, control);
// Check {value} map agains the {property_cell} map.
......@@ -220,8 +220,8 @@ Reduction JSGlobalObjectSpecialization::ReduceJSStoreGlobal(Node* node) {
representation = MachineRepresentation::kTaggedPointer;
} else {
// Check that the {value} is a Smi.
value = effect = graph()->NewNode(simplified()->CheckTaggedSigned(),
value, effect, control);
value = effect =
graph()->NewNode(simplified()->CheckSmi(), value, effect, control);
property_cell_value_type = Type::SignedSmall();
representation = MachineRepresentation::kTaggedSigned;
}
......
......@@ -168,7 +168,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
receiver, effect, control);
} else {
// Monomorphic property access.
effect = BuildCheckTaggedPointer(receiver, effect, control);
effect = BuildCheckHeapObject(receiver, effect, control);
effect = BuildCheckMaps(receiver, effect, control,
access_info.receiver_maps());
}
......@@ -206,7 +206,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
receiverissmi_control = graph()->NewNode(common()->IfTrue(), branch);
receiverissmi_effect = effect;
} else {
effect = BuildCheckTaggedPointer(receiver, effect, control);
effect = BuildCheckHeapObject(receiver, effect, control);
}
// Load the {receiver} map. The resulting effect is the dominating effect
......@@ -510,7 +510,7 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
}
// Ensure that {receiver} is a heap object.
effect = BuildCheckTaggedPointer(receiver, effect, control);
effect = BuildCheckHeapObject(receiver, effect, control);
// Check for the monomorphic case.
if (access_infos.size() == 1) {
......@@ -971,14 +971,14 @@ JSNativeContextSpecialization::BuildPropertyAccess(
break;
}
case MachineRepresentation::kTaggedSigned: {
value = effect = graph()->NewNode(simplified()->CheckTaggedSigned(),
value, effect, control);
value = effect = graph()->NewNode(simplified()->CheckSmi(), value,
effect, control);
field_access.write_barrier_kind = kNoWriteBarrier;
break;
}
case MachineRepresentation::kTaggedPointer: {
// Ensure that {value} is a HeapObject.
value = effect = graph()->NewNode(simplified()->CheckTaggedPointer(),
value = effect = graph()->NewNode(simplified()->CheckHeapObject(),
value, effect, control);
Handle<Map> field_map;
if (access_info.field_map().ToHandle(&field_map)) {
......@@ -1243,8 +1243,8 @@ JSNativeContextSpecialization::BuildElementAccess(
} else {
DCHECK_EQ(AccessMode::kStore, access_mode);
if (IsFastSmiElementsKind(elements_kind)) {
value = effect = graph()->NewNode(simplified()->CheckTaggedSigned(),
value, effect, control);
value = effect =
graph()->NewNode(simplified()->CheckSmi(), value, effect, control);
} else if (IsFastDoubleElementsKind(elements_kind)) {
value = effect = graph()->NewNode(simplified()->CheckNumber(), value,
effect, control);
......@@ -1315,9 +1315,9 @@ Node* JSNativeContextSpecialization::BuildCheckMaps(
inputs);
}
Node* JSNativeContextSpecialization::BuildCheckTaggedPointer(Node* receiver,
Node* effect,
Node* control) {
Node* JSNativeContextSpecialization::BuildCheckHeapObject(Node* receiver,
Node* effect,
Node* control) {
switch (receiver->opcode()) {
case IrOpcode::kHeapConstant:
case IrOpcode::kJSCreate:
......@@ -1336,8 +1336,8 @@ Node* JSNativeContextSpecialization::BuildCheckTaggedPointer(Node* receiver,
return effect;
}
default: {
return graph()->NewNode(simplified()->CheckTaggedPointer(), receiver,
effect, control);
return graph()->NewNode(simplified()->CheckHeapObject(), receiver, effect,
control);
}
}
}
......
......@@ -118,7 +118,7 @@ class JSNativeContextSpecialization final : public AdvancedReducer {
std::vector<Handle<Map>> const& maps);
// Construct an appropriate heap object check.
Node* BuildCheckTaggedPointer(Node* receiver, Node* effect, Node* control);
Node* BuildCheckHeapObject(Node* receiver, Node* effect, Node* control);
// Adds stability dependencies on all prototypes of every class in
// {receiver_type} up to (and including) the {holder}.
......
......@@ -190,12 +190,15 @@
V(CheckedUint32Div) \
V(CheckedUint32Mod) \
V(CheckedInt32Mul) \
V(CheckedInt32ToTaggedSigned) \
V(CheckedUint32ToInt32) \
V(CheckedUint32ToTaggedSigned) \
V(CheckedFloat64ToInt32) \
V(CheckedTaggedSignedToInt32) \
V(CheckedTaggedToInt32) \
V(CheckedTruncateTaggedToWord32) \
V(CheckedTaggedToFloat64)
V(CheckedTaggedToFloat64) \
V(CheckedTaggedToTaggedSigned)
#define SIMPLIFIED_COMPARE_BINOP_LIST(V) \
V(NumberEqual) \
......@@ -286,8 +289,8 @@
V(CheckMaps) \
V(CheckNumber) \
V(CheckString) \
V(CheckTaggedPointer) \
V(CheckTaggedSigned) \
V(CheckSmi) \
V(CheckHeapObject) \
V(CheckFloat64Hole) \
V(CheckTaggedHole) \
V(ConvertTaggedHoleToUndefined) \
......
......@@ -19,12 +19,12 @@ Reduction RedundancyElimination::Reduce(Node* node) {
switch (node->opcode()) {
case IrOpcode::kCheckBounds:
case IrOpcode::kCheckFloat64Hole:
case IrOpcode::kCheckHeapObject:
case IrOpcode::kCheckIf:
case IrOpcode::kCheckNumber:
case IrOpcode::kCheckSmi:
case IrOpcode::kCheckString:
case IrOpcode::kCheckTaggedHole:
case IrOpcode::kCheckTaggedPointer:
case IrOpcode::kCheckTaggedSigned:
case IrOpcode::kCheckedFloat64ToInt32:
case IrOpcode::kCheckedInt32Add:
case IrOpcode::kCheckedInt32Sub:
......
......@@ -142,8 +142,10 @@ Node* RepresentationChanger::GetRepresentationFor(
switch (use_info.representation()) {
case MachineRepresentation::kTaggedSigned:
DCHECK(use_info.type_check() == TypeCheckKind::kNone);
return GetTaggedSignedRepresentationFor(node, output_rep, output_type);
DCHECK(use_info.type_check() == TypeCheckKind::kNone ||
use_info.type_check() == TypeCheckKind::kSignedSmall);
return GetTaggedSignedRepresentationFor(node, output_rep, output_type,
use_node, use_info);
case MachineRepresentation::kTaggedPointer:
DCHECK(use_info.type_check() == TypeCheckKind::kNone);
return GetTaggedPointerRepresentationFor(node, output_rep, output_type);
......@@ -180,32 +182,15 @@ Node* RepresentationChanger::GetRepresentationFor(
}
Node* RepresentationChanger::GetTaggedSignedRepresentationFor(
Node* node, MachineRepresentation output_rep, Type* output_type) {
Node* node, MachineRepresentation output_rep, Type* output_type,
Node* use_node, UseInfo use_info) {
// Eagerly fold representation changes for constants.
switch (node->opcode()) {
case IrOpcode::kNumberConstant: {
int32_t value = OpParameter<int32_t>(node);
if (Smi::IsValid(value)) {
return jsgraph()->Constant(value);
}
return TypeError(node, output_rep, output_type,
MachineRepresentation::kTaggedSigned);
}
case IrOpcode::kHeapConstant:
return TypeError(node, output_rep, output_type,
MachineRepresentation::kTaggedSigned);
case IrOpcode::kInt32Constant:
case IrOpcode::kNumberConstant:
if (output_type->Is(Type::SignedSmall())) {
int32_t value = OpParameter<int32_t>(node);
return jsgraph()->Constant(value);
} else {
return TypeError(node, output_rep, output_type,
MachineRepresentation::kTaggedSigned);
return node;
}
case IrOpcode::kFloat64Constant:
case IrOpcode::kFloat32Constant:
return TypeError(node, output_rep, output_type,
MachineRepresentation::kTaggedSigned);
break;
default:
break;
}
......@@ -218,17 +203,72 @@ Node* RepresentationChanger::GetTaggedSignedRepresentationFor(
} else if (IsWord(output_rep)) {
if (output_type->Is(Type::Signed31())) {
op = simplified()->ChangeInt31ToTaggedSigned();
} else if (machine()->Is64() && output_type->Is(Type::Signed32())) {
op = simplified()->ChangeInt32ToTagged();
} else if (output_type->Is(Type::Signed32())) {
if (SmiValuesAre32Bits()) {
op = simplified()->ChangeInt32ToTagged();
} else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
op = simplified()->CheckedInt32ToTaggedSigned();
} else {
return TypeError(node, output_rep, output_type,
MachineRepresentation::kTaggedSigned);
}
} else if (output_type->Is(Type::Unsigned32()) &&
use_info.type_check() == TypeCheckKind::kSignedSmall) {
op = simplified()->CheckedUint32ToTaggedSigned();
} else {
return TypeError(node, output_rep, output_type,
MachineRepresentation::kTaggedSigned);
}
} else if (output_rep == MachineRepresentation::kFloat64) {
if (output_type->Is(Type::Signed31())) {
// float64 -> int32 -> tagged signed
node = InsertChangeFloat64ToInt32(node);
op = simplified()->ChangeInt31ToTaggedSigned();
} else if (output_type->Is(Type::Signed32())) {
// float64 -> int32 -> tagged signed
node = InsertChangeFloat64ToInt32(node);
if (SmiValuesAre32Bits()) {
op = simplified()->ChangeInt32ToTagged();
} else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
op = simplified()->CheckedInt32ToTaggedSigned();
} else {
return TypeError(node, output_rep, output_type,
MachineRepresentation::kTaggedSigned);
}
} else if (output_type->Is(Type::Unsigned32()) &&
use_info.type_check() == TypeCheckKind::kSignedSmall) {
// float64 -> uint32 -> tagged signed
node = InsertChangeFloat64ToUint32(node);
op = simplified()->CheckedUint32ToTaggedSigned();
} else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
op = simplified()->CheckedFloat64ToInt32(
output_type->Maybe(Type::MinusZero())
? CheckForMinusZeroMode::kCheckForMinusZero
: CheckForMinusZeroMode::kDontCheckForMinusZero);
node = InsertConversion(node, op, use_node);
if (SmiValuesAre32Bits()) {
op = simplified()->ChangeInt32ToTagged();
} else {
op = simplified()->CheckedInt32ToTaggedSigned();
}
} else {
return TypeError(node, output_rep, output_type,
MachineRepresentation::kTaggedSigned);
}
} else if (CanBeTaggedPointer(output_rep) &&
use_info.type_check() == TypeCheckKind::kSignedSmall) {
op = simplified()->CheckedTaggedToTaggedSigned();
} else if (output_rep == MachineRepresentation::kBit &&
use_info.type_check() == TypeCheckKind::kSignedSmall) {
// TODO(turbofan): Consider adding a Bailout operator that just deopts.
// Also use that for MachineRepresentation::kPointer case above.
node = InsertChangeBitToTagged(node);
op = simplified()->CheckedTaggedToTaggedSigned();
} else {
return TypeError(node, output_rep, output_type,
MachineRepresentation::kTaggedSigned);
}
return jsgraph()->graph()->NewNode(op, node);
return InsertConversion(node, op, use_node);
}
Node* RepresentationChanger::GetTaggedPointerRepresentationFor(
......@@ -933,6 +973,9 @@ Node* RepresentationChanger::TypeError(Node* node,
return node;
}
Node* RepresentationChanger::InsertChangeBitToTagged(Node* node) {
return jsgraph()->graph()->NewNode(simplified()->ChangeBitToTagged(), node);
}
Node* RepresentationChanger::InsertChangeFloat32ToFloat64(Node* node) {
return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(), node);
......
......@@ -150,6 +150,10 @@ class UseInfo {
}
// Possibly deoptimizing conversions.
static UseInfo CheckedSignedSmallAsTaggedSigned() {
return UseInfo(MachineRepresentation::kTaggedSigned, Truncation::Any(),
TypeCheckKind::kSignedSmall);
}
static UseInfo CheckedSignedSmallAsWord32() {
return UseInfo(MachineRepresentation::kWord32, Truncation::Any(),
TypeCheckKind::kSignedSmall);
......@@ -243,7 +247,8 @@ class RepresentationChanger final {
Node* GetTaggedSignedRepresentationFor(Node* node,
MachineRepresentation output_rep,
Type* output_type);
Type* output_type, Node* use_node,
UseInfo use_info);
Node* GetTaggedPointerRepresentationFor(Node* node,
MachineRepresentation output_rep,
Type* output_type);
......@@ -266,6 +271,7 @@ class RepresentationChanger final {
Node* TypeError(Node* node, MachineRepresentation output_rep,
Type* output_type, MachineRepresentation use);
Node* MakeTruncatedInt32Constant(double value);
Node* InsertChangeBitToTagged(Node* node);
Node* InsertChangeFloat32ToFloat64(Node* node);
Node* InsertChangeFloat64ToInt32(Node* node);
Node* InsertChangeFloat64ToUint32(Node* node);
......
......@@ -2126,6 +2126,15 @@ class RepresentationSelector {
}
return;
}
case IrOpcode::kCheckHeapObject: {
if (InputCannotBe(node, Type::SignedSmall())) {
VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
if (lower()) DeferReplacement(node, node->InputAt(0));
} else {
VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
}
return;
}
case IrOpcode::kCheckIf: {
ProcessInput(node, 0, UseInfo::Bool());
ProcessRemainingInputs(node, 1);
......@@ -2151,28 +2160,20 @@ class RepresentationSelector {
}
return;
}
case IrOpcode::kCheckString: {
if (InputIs(node, Type::String())) {
VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
if (lower()) DeferReplacement(node, node->InputAt(0));
case IrOpcode::kCheckSmi: {
if (SmiValuesAre32Bits() && truncation.IsUsedAsWord32()) {
VisitUnop(node, UseInfo::CheckedSignedSmallAsWord32(),
MachineRepresentation::kWord32);
} else {
VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
VisitUnop(node, UseInfo::CheckedSignedSmallAsTaggedSigned(),
MachineRepresentation::kTaggedSigned);
}
if (lower()) DeferReplacement(node, node->InputAt(0));
return;
}
case IrOpcode::kCheckTaggedPointer: {
if (InputCannotBe(node, Type::SignedSmall())) {
VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
if (lower()) DeferReplacement(node, node->InputAt(0));
} else {
case IrOpcode::kCheckString: {
if (InputIs(node, Type::String())) {
VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
}
return;
}
case IrOpcode::kCheckTaggedSigned: {
if (SmiValuesAre32Bits() && truncation.IsUsedAsWord32()) {
VisitUnop(node, UseInfo::CheckedSignedSmallAsWord32(),
MachineRepresentation::kWord32);
if (lower()) DeferReplacement(node, node->InputAt(0));
} else {
VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
......
......@@ -142,27 +142,27 @@ Reduction SimplifiedOperatorReducer::Reduce(Node* node) {
}
break;
}
case IrOpcode::kCheckTaggedPointer: {
case IrOpcode::kCheckHeapObject: {
Node* const input = node->InputAt(0);
if (DecideObjectIsSmi(input) == Decision::kFalse) {
ReplaceWithValue(node, input);
return Replace(input);
}
NodeMatcher m(input);
if (m.IsCheckTaggedPointer()) {
if (m.IsCheckHeapObject()) {
ReplaceWithValue(node, input);
return Replace(input);
}
break;
}
case IrOpcode::kCheckTaggedSigned: {
case IrOpcode::kCheckSmi: {
Node* const input = node->InputAt(0);
if (DecideObjectIsSmi(input) == Decision::kTrue) {
ReplaceWithValue(node, input);
return Replace(input);
}
NodeMatcher m(input);
if (m.IsCheckTaggedSigned()) {
if (m.IsCheckSmi()) {
ReplaceWithValue(node, input);
return Replace(input);
} else if (m.IsConvertTaggedHoleToUndefined()) {
......
......@@ -425,22 +425,25 @@ PretenureFlag PretenureFlagOf(const Operator* op) {
V(SpeculativeNumberLessThan) \
V(SpeculativeNumberLessThanOrEqual)
#define CHECKED_OP_LIST(V) \
V(CheckBounds, 2, 1) \
V(CheckIf, 1, 0) \
V(CheckNumber, 1, 1) \
V(CheckString, 1, 1) \
V(CheckTaggedHole, 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(CheckedTaggedSignedToInt32, 1, 1) \
#define CHECKED_OP_LIST(V) \
V(CheckBounds, 2, 1) \
V(CheckHeapObject, 1, 1) \
V(CheckIf, 1, 0) \
V(CheckNumber, 1, 1) \
V(CheckSmi, 1, 1) \
V(CheckString, 1, 1) \
V(CheckTaggedHole, 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(CheckedUint32ToTaggedSigned, 1, 1) \
V(CheckedInt32ToTaggedSigned, 1, 1) \
V(CheckedTaggedSignedToInt32, 1, 1) \
V(CheckedTaggedToTaggedSigned, 1, 1) \
V(CheckedTruncateTaggedToWord32, 1, 1)
struct SimplifiedOperatorGlobalCache final {
......
......@@ -311,10 +311,11 @@ class SimplifiedOperatorBuilder final : public ZoneObject {
const Operator* CheckIf();
const Operator* CheckBounds();
const Operator* CheckMaps(int map_input_count);
const Operator* CheckHeapObject();
const Operator* CheckNumber();
const Operator* CheckSmi();
const Operator* CheckString();
const Operator* CheckTaggedPointer();
const Operator* CheckTaggedSigned();
const Operator* CheckedInt32Add();
const Operator* CheckedInt32Sub();
......@@ -323,11 +324,14 @@ class SimplifiedOperatorBuilder final : public ZoneObject {
const Operator* CheckedUint32Div();
const Operator* CheckedUint32Mod();
const Operator* CheckedInt32Mul(CheckForMinusZeroMode);
const Operator* CheckedInt32ToTaggedSigned();
const Operator* CheckedUint32ToInt32();
const Operator* CheckedUint32ToTaggedSigned();
const Operator* CheckedFloat64ToInt32(CheckForMinusZeroMode);
const Operator* CheckedTaggedSignedToInt32();
const Operator* CheckedTaggedToInt32(CheckForMinusZeroMode);
const Operator* CheckedTaggedToFloat64(CheckTaggedInputMode);
const Operator* CheckedTaggedToTaggedSigned();
const Operator* CheckedTruncateTaggedToWord32();
const Operator* CheckFloat64Hole(CheckFloat64HoleMode);
......
......@@ -1571,6 +1571,16 @@ Type* Typer::Visitor::TypeCheckBounds(Node* node) {
return Type::Range(min, max, zone());
}
Type* Typer::Visitor::TypeCheckHeapObject(Node* node) {
Type* type = Operand(node, 0);
return type;
}
Type* Typer::Visitor::TypeCheckIf(Node* node) {
UNREACHABLE();
return nullptr;
}
Type* Typer::Visitor::TypeCheckMaps(Node* node) {
UNREACHABLE();
return nullptr;
......@@ -1581,24 +1591,14 @@ Type* Typer::Visitor::TypeCheckNumber(Node* node) {
return Type::Intersect(arg, Type::Number(), zone());
}
Type* Typer::Visitor::TypeCheckString(Node* node) {
Type* Typer::Visitor::TypeCheckSmi(Node* node) {
Type* arg = Operand(node, 0);
return Type::Intersect(arg, Type::String(), zone());
return Type::Intersect(arg, Type::SignedSmall(), zone());
}
Type* Typer::Visitor::TypeCheckIf(Node* node) {
UNREACHABLE();
return nullptr;
}
Type* Typer::Visitor::TypeCheckTaggedPointer(Node* node) {
Type* type = Operand(node, 0);
return type;
}
Type* Typer::Visitor::TypeCheckTaggedSigned(Node* node) {
Type* Typer::Visitor::TypeCheckString(Node* node) {
Type* arg = Operand(node, 0);
return Type::Intersect(arg, typer_->cache_.kSmi, zone());
return Type::Intersect(arg, Type::String(), zone());
}
Type* Typer::Visitor::TypeCheckFloat64Hole(Node* node) {
......
......@@ -1001,6 +1001,13 @@ void Verifier::Visitor::Check(Node* node) {
CheckValueInputIs(node, 1, Type::Unsigned31());
CheckTypeIs(node, Type::Unsigned31());
break;
case IrOpcode::kCheckHeapObject:
CheckValueInputIs(node, 0, Type::Any());
break;
case IrOpcode::kCheckIf:
CheckValueInputIs(node, 0, Type::Boolean());
CheckNotTyped(node);
break;
case IrOpcode::kCheckMaps:
// (Any, Internal, ..., Internal) -> Any
CheckValueInputIs(node, 0, Type::Any());
......@@ -1013,19 +1020,12 @@ void Verifier::Visitor::Check(Node* node) {
CheckValueInputIs(node, 0, Type::Any());
CheckTypeIs(node, Type::Number());
break;
case IrOpcode::kCheckString:
CheckValueInputIs(node, 0, Type::Any());
CheckTypeIs(node, Type::String());
break;
case IrOpcode::kCheckIf:
CheckValueInputIs(node, 0, Type::Boolean());
CheckNotTyped(node);
break;
case IrOpcode::kCheckTaggedSigned:
case IrOpcode::kCheckSmi:
CheckValueInputIs(node, 0, Type::Any());
break;
case IrOpcode::kCheckTaggedPointer:
case IrOpcode::kCheckString:
CheckValueInputIs(node, 0, Type::Any());
CheckTypeIs(node, Type::String());
break;
case IrOpcode::kCheckedInt32Add:
......@@ -1035,11 +1035,14 @@ void Verifier::Visitor::Check(Node* node) {
case IrOpcode::kCheckedUint32Div:
case IrOpcode::kCheckedUint32Mod:
case IrOpcode::kCheckedInt32Mul:
case IrOpcode::kCheckedInt32ToTaggedSigned:
case IrOpcode::kCheckedUint32ToInt32:
case IrOpcode::kCheckedUint32ToTaggedSigned:
case IrOpcode::kCheckedFloat64ToInt32:
case IrOpcode::kCheckedTaggedSignedToInt32:
case IrOpcode::kCheckedTaggedToInt32:
case IrOpcode::kCheckedTaggedToFloat64:
case IrOpcode::kCheckedTaggedToTaggedSigned:
case IrOpcode::kCheckedTruncateTaggedToWord32:
break;
......
......@@ -350,20 +350,20 @@ TEST_F(SimplifiedOperatorReducerTest, TruncateTaggedToWord32WithConstant) {
}
// -----------------------------------------------------------------------------
// CheckTaggedPointer
// CheckHeapObject
TEST_F(SimplifiedOperatorReducerTest, CheckTaggedPointerWithChangeBitToTagged) {
TEST_F(SimplifiedOperatorReducerTest, CheckHeapObjectWithChangeBitToTagged) {
Node* param0 = Parameter(0);
Node* effect = graph()->start();
Node* control = graph()->start();
Node* value = graph()->NewNode(simplified()->ChangeBitToTagged(), param0);
Reduction reduction = Reduce(graph()->NewNode(
simplified()->CheckTaggedPointer(), value, effect, control));
Reduction reduction = Reduce(graph()->NewNode(simplified()->CheckHeapObject(),
value, effect, control));
ASSERT_TRUE(reduction.Changed());
EXPECT_EQ(value, reduction.replacement());
}
TEST_F(SimplifiedOperatorReducerTest, CheckTaggedPointerWithHeapConstant) {
TEST_F(SimplifiedOperatorReducerTest, CheckHeapObjectWithHeapConstant) {
Node* effect = graph()->start();
Node* control = graph()->start();
Handle<HeapObject> kHeapObjects[] = {
......@@ -372,59 +372,57 @@ TEST_F(SimplifiedOperatorReducerTest, CheckTaggedPointerWithHeapConstant) {
TRACED_FOREACH(Handle<HeapObject>, object, kHeapObjects) {
Node* value = HeapConstant(object);
Reduction reduction = Reduce(graph()->NewNode(
simplified()->CheckTaggedPointer(), value, effect, control));
simplified()->CheckHeapObject(), value, effect, control));
ASSERT_TRUE(reduction.Changed());
EXPECT_EQ(value, reduction.replacement());
}
}
TEST_F(SimplifiedOperatorReducerTest,
CheckTaggedPointerWithCheckTaggedPointer) {
TEST_F(SimplifiedOperatorReducerTest, CheckHeapObjectWithCheckHeapObject) {
Node* param0 = Parameter(0);
Node* effect = graph()->start();
Node* control = graph()->start();
Node* value = effect = graph()->NewNode(simplified()->CheckTaggedPointer(),
Node* value = effect = graph()->NewNode(simplified()->CheckHeapObject(),
param0, effect, control);
Reduction reduction = Reduce(graph()->NewNode(
simplified()->CheckTaggedPointer(), value, effect, control));
Reduction reduction = Reduce(graph()->NewNode(simplified()->CheckHeapObject(),
value, effect, control));
ASSERT_TRUE(reduction.Changed());
EXPECT_EQ(value, reduction.replacement());
}
// -----------------------------------------------------------------------------
// CheckTaggedSigned
// CheckSmi
TEST_F(SimplifiedOperatorReducerTest,
CheckTaggedSignedWithChangeInt31ToTaggedSigned) {
TEST_F(SimplifiedOperatorReducerTest, CheckSmiWithChangeInt31ToTaggedSigned) {
Node* param0 = Parameter(0);
Node* effect = graph()->start();
Node* control = graph()->start();
Node* value =
graph()->NewNode(simplified()->ChangeInt31ToTaggedSigned(), param0);
Reduction reduction = Reduce(graph()->NewNode(
simplified()->CheckTaggedSigned(), value, effect, control));
Reduction reduction = Reduce(
graph()->NewNode(simplified()->CheckSmi(), value, effect, control));
ASSERT_TRUE(reduction.Changed());
EXPECT_EQ(value, reduction.replacement());
}
TEST_F(SimplifiedOperatorReducerTest, CheckTaggedSignedWithNumberConstant) {
TEST_F(SimplifiedOperatorReducerTest, CheckSmiWithNumberConstant) {
Node* effect = graph()->start();
Node* control = graph()->start();
Node* value = NumberConstant(1.0);
Reduction reduction = Reduce(graph()->NewNode(
simplified()->CheckTaggedSigned(), value, effect, control));
Reduction reduction = Reduce(
graph()->NewNode(simplified()->CheckSmi(), value, effect, control));
ASSERT_TRUE(reduction.Changed());
EXPECT_EQ(value, reduction.replacement());
}
TEST_F(SimplifiedOperatorReducerTest, CheckTaggedSignedWithCheckTaggedSigned) {
TEST_F(SimplifiedOperatorReducerTest, CheckSmiWithCheckSmi) {
Node* param0 = Parameter(0);
Node* effect = graph()->start();
Node* control = graph()->start();
Node* value = effect = graph()->NewNode(simplified()->CheckTaggedSigned(),
param0, effect, control);
Reduction reduction = Reduce(graph()->NewNode(
simplified()->CheckTaggedSigned(), value, effect, control));
Node* value = effect =
graph()->NewNode(simplified()->CheckSmi(), param0, effect, control);
Reduction reduction = Reduce(
graph()->NewNode(simplified()->CheckSmi(), value, effect, control));
ASSERT_TRUE(reduction.Changed());
EXPECT_EQ(value, reduction.replacement());
}
......
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