[turbofan] Address the useless overflow bit materialization.

Add control dependencies to Projection and Int32Add/SubWithOverflow
operators, to prevent the scheduler from moving the Projection nodes
into the wrong place. This way the instruction selection can combine
the Int32Add/SubWithOverflow operations with the DeoptimizeIf and/or
DeoptimizeUnless nodes. This needs new operators CheckedInt32Add and
CheckedInt32Sub so that we can delay the actual lowering until the
effect/control linearizer.

This also makes CheckIf operator obsolete, so we can drop it.

R=jarin@chromium.org

Review-Url: https://codereview.chromium.org/2082993002
Cr-Commit-Position: refs/heads/master@{#37148}
This commit is contained in:
bmeurer 2016-06-21 08:46:10 -07:00 committed by Commit bot
parent 76368d0854
commit 00889cc29c
16 changed files with 223 additions and 140 deletions

View File

@ -469,7 +469,7 @@ struct CommonOperatorGlobalCache final {
IrOpcode::kProjection, // opcode
Operator::kPure, // flags
"Projection", // name
1, 0, 0, 1, 0, 0, // counts,
1, 0, 1, 1, 0, 0, // counts,
kIndex) {} // parameter
};
#define CACHED_PROJECTION(index) \
@ -915,12 +915,12 @@ const Operator* CommonOperatorBuilder::Projection(size_t index) {
break;
}
// Uncached.
return new (zone()) Operator1<size_t>( // --
IrOpcode::kProjection, // opcode
Operator::kFoldable | Operator::kNoThrow, // flags
"Projection", // name
1, 0, 0, 1, 0, 0, // counts
index); // parameter
return new (zone()) Operator1<size_t>( // --
IrOpcode::kProjection, // opcode
Operator::kPure, // flags
"Projection", // name
1, 0, 1, 1, 0, 0, // counts
index); // parameter
}

View File

@ -440,6 +440,12 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kCheckTaggedSigned:
state = LowerCheckTaggedSigned(node, frame_state, *effect, *control);
break;
case IrOpcode::kCheckedInt32Add:
state = LowerCheckedInt32Add(node, frame_state, *effect, *control);
break;
case IrOpcode::kCheckedInt32Sub:
state = LowerCheckedInt32Sub(node, frame_state, *effect, *control);
break;
case IrOpcode::kCheckedUint32ToInt32:
state = LowerCheckedUint32ToInt32(node, frame_state, *effect, *control);
break;
@ -476,9 +482,6 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kStringFromCharCode:
state = LowerStringFromCharCode(node, *effect, *control);
break;
case IrOpcode::kCheckIf:
state = LowerCheckIf(node, frame_state, *effect, *control);
break;
case IrOpcode::kCheckFloat64Hole:
state = LowerCheckFloat64Hole(node, frame_state, *effect, *control);
break;
@ -554,10 +557,11 @@ EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node, Node* effect,
if (machine()->Is64()) {
vsmi = ChangeInt32ToSmi(value32);
} else {
Node* smi_tag =
graph()->NewNode(machine()->Int32AddWithOverflow(), value32, value32);
Node* smi_tag = graph()->NewNode(machine()->Int32AddWithOverflow(), value32,
value32, if_smi);
Node* check_ovf = graph()->NewNode(common()->Projection(1), smi_tag);
Node* check_ovf =
graph()->NewNode(common()->Projection(1), smi_tag, if_smi);
Node* branch_ovf = graph()->NewNode(common()->Branch(BranchHint::kFalse),
check_ovf, if_smi);
@ -565,7 +569,7 @@ EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node, Node* effect,
if_box = graph()->NewNode(common()->Merge(2), if_ovf, if_box);
if_smi = graph()->NewNode(common()->IfFalse(), branch_ovf);
vsmi = graph()->NewNode(common()->Projection(0), smi_tag);
vsmi = graph()->NewNode(common()->Projection(0), smi_tag, if_smi);
}
// Allocate the box for the {value}.
@ -617,9 +621,10 @@ EffectControlLinearizer::LowerChangeInt32ToTagged(Node* node, Node* effect,
return ValueEffectControl(ChangeInt32ToSmi(value), effect, control);
}
Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), value, value);
Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), value, value,
control);
Node* ovf = graph()->NewNode(common()->Projection(1), add);
Node* ovf = graph()->NewNode(common()->Projection(1), add, control);
Node* branch =
graph()->NewNode(common()->Branch(BranchHint::kFalse), ovf, control);
@ -628,7 +633,7 @@ EffectControlLinearizer::LowerChangeInt32ToTagged(Node* node, Node* effect,
AllocateHeapNumberWithValue(ChangeInt32ToFloat64(value), effect, if_true);
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* vfalse = graph()->NewNode(common()->Projection(0), add);
Node* vfalse = graph()->NewNode(common()->Projection(0), add, if_false);
Node* merge = graph()->NewNode(common()->Merge(2), alloc.control, if_false);
Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
@ -834,6 +839,48 @@ EffectControlLinearizer::LowerCheckTaggedSigned(Node* node, Node* frame_state,
return ValueEffectControl(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckedInt32Add(Node* node, Node* frame_state,
Node* effect, Node* control) {
Node* lhs = node->InputAt(0);
Node* rhs = node->InputAt(1);
Node* value =
graph()->NewNode(machine()->Int32AddWithOverflow(), lhs, rhs, control);
Node* check = graph()->NewNode(common()->Projection(1), value, control);
control = effect = graph()->NewNode(common()->DeoptimizeIf(), check,
frame_state, effect, control);
value = graph()->NewNode(common()->Projection(0), value, control);
// Make sure the lowered node does not appear in any use lists.
node->TrimInputCount(0);
return ValueEffectControl(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckedInt32Sub(Node* node, Node* frame_state,
Node* effect, Node* control) {
Node* lhs = node->InputAt(0);
Node* rhs = node->InputAt(1);
Node* value =
graph()->NewNode(machine()->Int32SubWithOverflow(), lhs, rhs, control);
Node* check = graph()->NewNode(common()->Projection(1), value, control);
control = effect = graph()->NewNode(common()->DeoptimizeIf(), check,
frame_state, effect, control);
value = graph()->NewNode(common()->Projection(0), value, control);
// Make sure the lowered node does not appear in any use lists.
node->TrimInputCount(0);
return ValueEffectControl(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node,
Node* frame_state,
@ -1371,17 +1418,6 @@ EffectControlLinearizer::LowerStringFromCharCode(Node* node, Node* effect,
return ValueEffectControl(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckIf(Node* node, Node* frame_state,
Node* effect, Node* control) {
NodeProperties::ReplaceEffectInput(node, effect);
NodeProperties::ReplaceControlInput(node, control);
DCHECK_NOT_NULL(frame_state);
node->InsertInput(graph()->zone(), 1, frame_state);
NodeProperties::ChangeOp(node, common()->DeoptimizeIf());
return ValueEffectControl(node, node, node);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckFloat64Hole(Node* node, Node* frame_state,
Node* effect, Node* control) {

View File

@ -68,6 +68,10 @@ class EffectControlLinearizer {
Node* effect, Node* control);
ValueEffectControl LowerCheckTaggedSigned(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,
Node* effect, Node* control);
ValueEffectControl LowerCheckedUint32ToInt32(Node* node, Node* frame_state,
Node* effect, Node* control);
ValueEffectControl LowerCheckedFloat64ToInt32(Node* node, Node* frame_state,
@ -99,8 +103,6 @@ class EffectControlLinearizer {
Node* effect, Node* control);
ValueEffectControl LowerCheckTaggedHole(Node* node, Node* frame_state,
Node* effect, Node* control);
ValueEffectControl LowerCheckIf(Node* node, Node* frame_state, Node* effect,
Node* control);
ValueEffectControl LowerPlainPrimitiveToNumber(Node* node, Node* effect,
Node* control);
ValueEffectControl LowerPlainPrimitiveToWord32(Node* node, Node* effect,

View File

@ -243,8 +243,10 @@ void Int64Lowering::LowerNode(Node* node) {
if (descriptor->ReturnCount() == 1 &&
descriptor->GetReturnType(0) == MachineType::Int64()) {
// We access the additional return values through projections.
Node* low_node = graph()->NewNode(common()->Projection(0), node);
Node* high_node = graph()->NewNode(common()->Projection(1), node);
Node* low_node =
graph()->NewNode(common()->Projection(0), node, graph()->start());
Node* high_node =
graph()->NewNode(common()->Projection(1), node, graph()->start());
ReplaceNode(node, low_node, high_node);
}
break;
@ -283,8 +285,10 @@ void Int64Lowering::LowerNode(Node* node) {
NodeProperties::ChangeOp(node, machine()->Int32PairAdd());
// We access the additional return values through projections.
Node* low_node = graph()->NewNode(common()->Projection(0), node);
Node* high_node = graph()->NewNode(common()->Projection(1), node);
Node* low_node =
graph()->NewNode(common()->Projection(0), node, graph()->start());
Node* high_node =
graph()->NewNode(common()->Projection(1), node, graph()->start());
ReplaceNode(node, low_node, high_node);
break;
}
@ -301,8 +305,10 @@ void Int64Lowering::LowerNode(Node* node) {
NodeProperties::ChangeOp(node, machine()->Int32PairSub());
// We access the additional return values through projections.
Node* low_node = graph()->NewNode(common()->Projection(0), node);
Node* high_node = graph()->NewNode(common()->Projection(1), node);
Node* low_node =
graph()->NewNode(common()->Projection(0), node, graph()->start());
Node* high_node =
graph()->NewNode(common()->Projection(1), node, graph()->start());
ReplaceNode(node, low_node, high_node);
break;
}
@ -319,8 +325,10 @@ void Int64Lowering::LowerNode(Node* node) {
NodeProperties::ChangeOp(node, machine()->Int32PairMul());
// We access the additional return values through projections.
Node* low_node = graph()->NewNode(common()->Projection(0), node);
Node* high_node = graph()->NewNode(common()->Projection(1), node);
Node* low_node =
graph()->NewNode(common()->Projection(0), node, graph()->start());
Node* high_node =
graph()->NewNode(common()->Projection(1), node, graph()->start());
ReplaceNode(node, low_node, high_node);
break;
}
@ -369,8 +377,10 @@ void Int64Lowering::LowerNode(Node* node) {
NodeProperties::ChangeOp(node, machine()->Word32PairShl());
// We access the additional return values through projections.
Node* low_node = graph()->NewNode(common()->Projection(0), node);
Node* high_node = graph()->NewNode(common()->Projection(1), node);
Node* low_node =
graph()->NewNode(common()->Projection(0), node, graph()->start());
Node* high_node =
graph()->NewNode(common()->Projection(1), node, graph()->start());
ReplaceNode(node, low_node, high_node);
break;
}
@ -391,8 +401,10 @@ void Int64Lowering::LowerNode(Node* node) {
NodeProperties::ChangeOp(node, machine()->Word32PairShr());
// We access the additional return values through projections.
Node* low_node = graph()->NewNode(common()->Projection(0), node);
Node* high_node = graph()->NewNode(common()->Projection(1), node);
Node* low_node =
graph()->NewNode(common()->Projection(0), node, graph()->start());
Node* high_node =
graph()->NewNode(common()->Projection(1), node, graph()->start());
ReplaceNode(node, low_node, high_node);
break;
}
@ -413,8 +425,10 @@ void Int64Lowering::LowerNode(Node* node) {
NodeProperties::ChangeOp(node, machine()->Word32PairSar());
// We access the additional return values through projections.
Node* low_node = graph()->NewNode(common()->Projection(0), node);
Node* high_node = graph()->NewNode(common()->Projection(1), node);
Node* low_node =
graph()->NewNode(common()->Projection(0), node, graph()->start());
Node* high_node =
graph()->NewNode(common()->Projection(1), node, graph()->start());
ReplaceNode(node, low_node, high_node);
break;
}

View File

@ -88,10 +88,7 @@ MachineRepresentation AtomicStoreRepresentationOf(Operator const* op) {
V(Word64Clz, Operator::kNoProperties, 1, 0, 1) \
V(Word64Equal, Operator::kCommutative, 2, 0, 1) \
V(Int32Add, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \
V(Int32AddWithOverflow, Operator::kAssociative | Operator::kCommutative, 2, \
0, 2) \
V(Int32Sub, Operator::kNoProperties, 2, 0, 1) \
V(Int32SubWithOverflow, Operator::kNoProperties, 2, 0, 2) \
V(Int32Mul, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \
V(Int32MulHigh, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \
V(Int32Div, Operator::kNoProperties, 2, 1, 1) \
@ -104,10 +101,7 @@ MachineRepresentation AtomicStoreRepresentationOf(Operator const* op) {
V(Uint32Mod, Operator::kNoProperties, 2, 1, 1) \
V(Uint32MulHigh, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \
V(Int64Add, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \
V(Int64AddWithOverflow, Operator::kAssociative | Operator::kCommutative, 2, \
0, 2) \
V(Int64Sub, Operator::kNoProperties, 2, 0, 1) \
V(Int64SubWithOverflow, Operator::kNoProperties, 2, 0, 2) \
V(Int64Mul, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \
V(Int64Div, Operator::kNoProperties, 2, 1, 1) \
V(Int64Mod, Operator::kNoProperties, 2, 1, 1) \
@ -390,6 +384,12 @@ MachineRepresentation AtomicStoreRepresentationOf(Operator const* op) {
V(Float32Neg, Operator::kNoProperties, 1, 0, 1) \
V(Float64Neg, Operator::kNoProperties, 1, 0, 1)
#define OVERFLOW_OP_LIST(V) \
V(Int32AddWithOverflow, Operator::kAssociative | Operator::kCommutative) \
V(Int32SubWithOverflow, Operator::kNoProperties) \
V(Int64AddWithOverflow, Operator::kAssociative | Operator::kCommutative) \
V(Int64SubWithOverflow, Operator::kNoProperties)
#define MACHINE_TYPE_LIST(V) \
V(Float32) \
V(Float64) \
@ -442,6 +442,17 @@ struct MachineOperatorGlobalCache {
PURE_OPTIONAL_OP_LIST(PURE)
#undef PURE
#define OVERFLOW_OP(Name, properties) \
struct Name##Operator final : public Operator { \
Name##Operator() \
: Operator(IrOpcode::k##Name, \
Operator::kEliminatable | Operator::kNoRead | properties, \
#Name, 2, 0, 1, 2, 0, 0) {} \
}; \
Name##Operator k##Name;
OVERFLOW_OP_LIST(OVERFLOW_OP)
#undef OVERFLOW_OP
#define LOAD(Type) \
struct Load##Type##Operator final : public Operator1<LoadRepresentation> { \
Load##Type##Operator() \
@ -594,6 +605,10 @@ PURE_OP_LIST(PURE)
PURE_OPTIONAL_OP_LIST(PURE)
#undef PURE
#define OVERFLOW_OP(Name, properties) \
const Operator* MachineOperatorBuilder::Name() { return &cache_.k##Name; }
OVERFLOW_OP_LIST(OVERFLOW_OP)
#undef OVERFLOW_OP
const Operator* MachineOperatorBuilder::Load(LoadRepresentation rep) {
#define LOAD(Type) \

View File

@ -238,13 +238,14 @@
V(CheckBounds) \
V(CheckTaggedPointer) \
V(CheckTaggedSigned) \
V(CheckedInt32Add) \
V(CheckedInt32Sub) \
V(CheckedUint32ToInt32) \
V(CheckedFloat64ToInt32) \
V(CheckedTaggedToInt32) \
V(CheckedTaggedToFloat64) \
V(CheckFloat64Hole) \
V(CheckTaggedHole) \
V(CheckIf) \
V(TruncateTaggedToWord32) \
V(TruncateTaggedToFloat64) \
V(Allocate) \

View File

@ -604,9 +604,9 @@ const Operator* RepresentationChanger::Int32OverflowOperatorFor(
IrOpcode::Value opcode) {
switch (opcode) {
case IrOpcode::kSpeculativeNumberAdd: // Fall through.
return machine()->Int32AddWithOverflow();
return simplified()->CheckedInt32Add();
case IrOpcode::kSpeculativeNumberSubtract: // Fall through.
return machine()->Int32SubWithOverflow();
return simplified()->CheckedInt32Sub();
default:
UNREACHABLE();
return nullptr;

View File

@ -1091,16 +1091,8 @@ class RepresentationSelector {
NodeProperties::ChangeOp(node, new_op);
}
void ChangeToInt32OverflowOp(Node* node, const Operator* op) {
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* arith = graph()->NewNode(op, node->InputAt(0), node->InputAt(1));
Node* overflow = graph()->NewNode(common()->Projection(1), arith);
effect =
graph()->NewNode(simplified()->CheckIf(), overflow, effect, control);
Node* value = graph()->NewNode(common()->Projection(0), arith);
ReplaceEffectControlUses(node, effect, control);
DeferReplacement(node, value);
void ChangeToInt32OverflowOp(Node* node, const Operator* new_op) {
NodeProperties::ChangeOp(node, new_op);
}
void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation,
@ -2037,6 +2029,8 @@ class RepresentationSelector {
case IrOpcode::kChangeFloat64ToUint32:
case IrOpcode::kTruncateInt64ToInt32:
case IrOpcode::kChangeFloat32ToFloat64:
case IrOpcode::kCheckedInt32Add:
case IrOpcode::kCheckedInt32Sub:
case IrOpcode::kCheckedUint32ToInt32:
case IrOpcode::kCheckedFloat64ToInt32:
case IrOpcode::kCheckedTaggedToInt32:

View File

@ -308,13 +308,15 @@ CompareOperationHints::Hint CompareOperationHintOf(const Operator* op) {
V(SpeculativeNumberMultiply) \
V(SpeculativeNumberModulus)
#define CHECKED_OP_LIST(V) \
V(CheckTaggedPointer) \
V(CheckTaggedSigned) \
V(CheckedUint32ToInt32) \
V(CheckedFloat64ToInt32) \
V(CheckedTaggedToInt32) \
V(CheckedTaggedToFloat64)
#define CHECKED_OP_LIST(V) \
V(CheckTaggedPointer, 1) \
V(CheckTaggedSigned, 1) \
V(CheckedInt32Add, 2) \
V(CheckedInt32Sub, 2) \
V(CheckedUint32ToInt32, 1) \
V(CheckedFloat64ToInt32, 1) \
V(CheckedTaggedToInt32, 1) \
V(CheckedTaggedToFloat64, 1)
struct SimplifiedOperatorGlobalCache final {
#define PURE(Name, properties, input_count) \
@ -327,29 +329,29 @@ struct SimplifiedOperatorGlobalCache final {
PURE_OP_LIST(PURE)
#undef PURE
#define CHECKED(Name) \
struct Name##Operator final : public Operator { \
Name##Operator() \
: Operator(IrOpcode::k##Name, \
Operator::kFoldable | Operator::kNoThrow, #Name, 1, 1, 1, \
1, 1, 0) {} \
}; \
#define CHECKED(Name, value_input_count) \
struct Name##Operator final : public Operator { \
Name##Operator() \
: Operator(IrOpcode::k##Name, \
Operator::kFoldable | Operator::kNoThrow, #Name, \
value_input_count, 1, 1, 1, 1, 0) {} \
}; \
Name##Operator k##Name;
CHECKED_OP_LIST(CHECKED)
#undef CHECKED
template <CheckFloat64HoleMode kMode>
struct CheckFloat64HoleNaNOperatortor final
struct CheckFloat64HoleNaNOperator final
: public Operator1<CheckFloat64HoleMode> {
CheckFloat64HoleNaNOperatortor()
CheckFloat64HoleNaNOperator()
: Operator1<CheckFloat64HoleMode>(
IrOpcode::kCheckFloat64Hole,
Operator::kFoldable | Operator::kNoDeopt, "CheckFloat64Hole", 1,
Operator::kFoldable | Operator::kNoThrow, "CheckFloat64Hole", 1,
1, 1, 1, 1, 0, kMode) {}
};
CheckFloat64HoleNaNOperatortor<CheckFloat64HoleMode::kAllowReturnHole>
CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kAllowReturnHole>
kCheckFloat64HoleAllowReturnHoleOperator;
CheckFloat64HoleNaNOperatortor<CheckFloat64HoleMode::kNeverReturnHole>
CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kNeverReturnHole>
kCheckFloat64HoleNeverReturnHoleOperator;
template <CheckTaggedHoleMode kMode>
@ -357,7 +359,7 @@ struct SimplifiedOperatorGlobalCache final {
CheckTaggedHoleOperator()
: Operator1<CheckTaggedHoleMode>(
IrOpcode::kCheckTaggedHole,
Operator::kFoldable | Operator::kNoDeopt, "CheckTaggedHole", 1, 1,
Operator::kFoldable | Operator::kNoThrow, "CheckTaggedHole", 1, 1,
1, 1, 1, 0, kMode) {}
};
CheckTaggedHoleOperator<CheckTaggedHoleMode::kConvertHoleToUndefined>
@ -365,13 +367,6 @@ struct SimplifiedOperatorGlobalCache final {
CheckTaggedHoleOperator<CheckTaggedHoleMode::kNeverReturnHole>
kCheckTaggedHoleNeverReturnHoleOperator;
struct CheckIfOperator final : public Operator {
CheckIfOperator()
: Operator(IrOpcode::kCheckIf, Operator::kFoldable | Operator::kNoDeopt,
"CheckIf", 1, 1, 1, 0, 1, 0) {}
};
CheckIfOperator kCheckIf;
template <PretenureFlag kPretenure>
struct AllocateOperator final : public Operator1<PretenureFlag> {
AllocateOperator()
@ -419,7 +414,7 @@ SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone)
PURE_OP_LIST(GET_FROM_CACHE)
#undef GET_FROM_CACHE
#define GET_FROM_CACHE(Name) \
#define GET_FROM_CACHE(Name, value_input_count) \
const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; }
CHECKED_OP_LIST(GET_FROM_CACHE)
#undef GET_FROM_CACHE
@ -448,10 +443,6 @@ const Operator* SimplifiedOperatorBuilder::CheckTaggedHole(
return nullptr;
}
const Operator* SimplifiedOperatorBuilder::CheckIf() {
return &cache_.kCheckIf;
}
const Operator* SimplifiedOperatorBuilder::ReferenceEqual(Type* type) {
return new (zone()) Operator(IrOpcode::kReferenceEqual,
Operator::kCommutative | Operator::kPure,

View File

@ -240,6 +240,8 @@ class SimplifiedOperatorBuilder final : public ZoneObject {
const Operator* CheckTaggedPointer();
const Operator* CheckTaggedSigned();
const Operator* CheckedInt32Add();
const Operator* CheckedInt32Sub();
const Operator* CheckedUint32ToInt32();
const Operator* CheckedFloat64ToInt32();
const Operator* CheckedTaggedToInt32();
@ -247,7 +249,6 @@ class SimplifiedOperatorBuilder final : public ZoneObject {
const Operator* CheckFloat64Hole(CheckFloat64HoleMode);
const Operator* CheckTaggedHole(CheckTaggedHoleMode);
const Operator* CheckIf();
const Operator* ObjectIsCallable();
const Operator* ObjectIsNumber();

View File

@ -2018,6 +2018,14 @@ Type* Typer::Visitor::TypeCheckTaggedSigned(Node* node) {
return Type::Intersect(arg, typer_->cache_.kSmi, zone());
}
Type* Typer::Visitor::TypeCheckedInt32Add(Node* node) {
return Type::Integral32();
}
Type* Typer::Visitor::TypeCheckedInt32Sub(Node* node) {
return Type::Integral32();
}
Type* Typer::Visitor::TypeCheckedUint32ToInt32(Node* node) {
return Type::Signed32();
}
@ -2057,11 +2065,6 @@ Type* Typer::Visitor::TypeCheckTaggedHole(Node* node) {
return type;
}
Type* Typer::Visitor::TypeCheckIf(Node* node) {
UNREACHABLE();
return nullptr;
}
Type* Typer::Visitor::TypeTruncateTaggedToWord32(Node* node) {
Type* arg = Operand(node, 0);
// TODO(jarin): DCHECK(arg->Is(Type::NumberOrUndefined()));

View File

@ -278,7 +278,6 @@ void Verifier::Visitor::Check(Node* node) {
break;
case IrOpcode::kDeoptimizeIf:
case IrOpcode::kDeoptimizeUnless:
case IrOpcode::kCheckIf:
// Type is empty.
CheckNotTyped(node);
break;
@ -956,6 +955,8 @@ void Verifier::Visitor::Check(Node* node) {
CheckUpperIs(node, Type::TaggedPointer());
break;
case IrOpcode::kCheckedInt32Add:
case IrOpcode::kCheckedInt32Sub:
case IrOpcode::kCheckedUint32ToInt32:
case IrOpcode::kCheckedFloat64ToInt32:
case IrOpcode::kCheckedTaggedToInt32:

View File

@ -1479,9 +1479,10 @@ Node* WasmGraphBuilder::BuildI64SConvertF32(Node* input,
} else {
Node* trunc = graph()->NewNode(
jsgraph()->machine()->TryTruncateFloat32ToInt64(), input);
Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc);
Node* overflow =
graph()->NewNode(jsgraph()->common()->Projection(1), trunc);
Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc,
graph()->start());
Node* overflow = graph()->NewNode(jsgraph()->common()->Projection(1), trunc,
graph()->start());
trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position);
return result;
}
@ -1496,9 +1497,10 @@ Node* WasmGraphBuilder::BuildI64UConvertF32(Node* input,
} else {
Node* trunc = graph()->NewNode(
jsgraph()->machine()->TryTruncateFloat32ToUint64(), input);
Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc);
Node* overflow =
graph()->NewNode(jsgraph()->common()->Projection(1), trunc);
Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc,
graph()->start());
Node* overflow = graph()->NewNode(jsgraph()->common()->Projection(1), trunc,
graph()->start());
trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position);
return result;
}
@ -1513,9 +1515,10 @@ Node* WasmGraphBuilder::BuildI64SConvertF64(Node* input,
} else {
Node* trunc = graph()->NewNode(
jsgraph()->machine()->TryTruncateFloat64ToInt64(), input);
Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc);
Node* overflow =
graph()->NewNode(jsgraph()->common()->Projection(1), trunc);
Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc,
graph()->start());
Node* overflow = graph()->NewNode(jsgraph()->common()->Projection(1), trunc,
graph()->start());
trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position);
return result;
}
@ -1530,9 +1533,10 @@ Node* WasmGraphBuilder::BuildI64UConvertF64(Node* input,
} else {
Node* trunc = graph()->NewNode(
jsgraph()->machine()->TryTruncateFloat64ToUint64(), input);
Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc);
Node* overflow =
graph()->NewNode(jsgraph()->common()->Projection(1), trunc);
Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc,
graph()->start());
Node* overflow = graph()->NewNode(jsgraph()->common()->Projection(1), trunc,
graph()->start());
trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position);
return result;
}
@ -1975,9 +1979,10 @@ Node* WasmGraphBuilder::BuildChangeInt32ToTagged(Node* value) {
return BuildChangeInt32ToSmi(value);
}
Node* add = graph()->NewNode(machine->Int32AddWithOverflow(), value, value);
Node* add = graph()->NewNode(machine->Int32AddWithOverflow(), value, value,
graph()->start());
Node* ovf = graph()->NewNode(common->Projection(1), add);
Node* ovf = graph()->NewNode(common->Projection(1), add, graph()->start());
Node* branch = graph()->NewNode(common->Branch(BranchHint::kFalse), ovf,
graph()->start());
@ -1986,7 +1991,7 @@ Node* WasmGraphBuilder::BuildChangeInt32ToTagged(Node* value) {
graph()->NewNode(machine->ChangeInt32ToFloat64(), value), if_true);
Node* if_false = graph()->NewNode(common->IfFalse(), branch);
Node* vfalse = graph()->NewNode(common->Projection(0), add);
Node* vfalse = graph()->NewNode(common->Projection(0), add, if_false);
Node* merge = graph()->NewNode(common->Merge(2), if_true, if_false);
Node* phi = graph()->NewNode(common->Phi(MachineRepresentation::kTagged, 2),
@ -2039,10 +2044,10 @@ Node* WasmGraphBuilder::BuildChangeFloat64ToTagged(Node* value) {
if (machine->Is64()) {
vsmi = BuildChangeInt32ToSmi(value32);
} else {
Node* smi_tag =
graph()->NewNode(machine->Int32AddWithOverflow(), value32, value32);
Node* smi_tag = graph()->NewNode(machine->Int32AddWithOverflow(), value32,
value32, if_smi);
Node* check_ovf = graph()->NewNode(common->Projection(1), smi_tag);
Node* check_ovf = graph()->NewNode(common->Projection(1), smi_tag, if_smi);
Node* branch_ovf =
graph()->NewNode(common->Branch(BranchHint::kFalse), check_ovf, if_smi);
@ -2050,7 +2055,7 @@ Node* WasmGraphBuilder::BuildChangeFloat64ToTagged(Node* value) {
if_box = graph()->NewNode(common->Merge(2), if_ovf, if_box);
if_smi = graph()->NewNode(common->IfFalse(), branch_ovf);
vsmi = graph()->NewNode(common->Projection(0), smi_tag);
vsmi = graph()->NewNode(common->Projection(0), smi_tag, if_smi);
}
// Allocate the box for the {value}.
@ -2383,7 +2388,8 @@ void WasmGraphBuilder::BuildJSToWasmWrapper(Handle<Code> wasm_code,
if (jsgraph()->machine()->Is32() && sig->return_count() > 0 &&
sig->GetReturn(0) == wasm::kAstI64) {
// The return values comes as two values, we pick the low word.
retval = graph()->NewNode(jsgraph()->common()->Projection(0), retval);
retval = graph()->NewNode(jsgraph()->common()->Projection(0), retval,
graph()->start());
}
Node* jsval =
ToJS(retval, context,

View File

@ -392,6 +392,19 @@ TEST_F(CommonOperatorTest, FinishRegion) {
EXPECT_EQ(1, op->ValueOutputCount());
}
TEST_F(CommonOperatorTest, Projection) {
TRACED_FORRANGE(size_t, index, 0, 3) {
const Operator* op = common()->Projection(index);
EXPECT_EQ(index, ProjectionIndexOf(op));
EXPECT_EQ(1, op->ValueInputCount());
EXPECT_EQ(1, op->ControlInputCount());
EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op));
EXPECT_EQ(0, op->ControlOutputCount());
EXPECT_EQ(0, op->EffectOutputCount());
EXPECT_EQ(1, op->ValueOutputCount());
}
}
} // namespace compiler
} // namespace internal
} // namespace v8

View File

@ -1284,28 +1284,31 @@ TEST_F(MachineOperatorReducerTest, Int32AddWithInt32SubWithConstantZero) {
TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithZero) {
Node* control = graph()->start();
Node* p0 = Parameter(0);
{
Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(),
Int32Constant(0), p0);
Int32Constant(0), p0, control);
Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
Reduction r =
Reduce(graph()->NewNode(common()->Projection(1), add, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsInt32Constant(0));
r = Reduce(graph()->NewNode(common()->Projection(0), add));
r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
ASSERT_TRUE(r.Changed());
EXPECT_EQ(p0, r.replacement());
}
{
Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), p0,
Int32Constant(0));
Int32Constant(0), control);
Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
Reduction r =
Reduce(graph()->NewNode(common()->Projection(1), add, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsInt32Constant(0));
r = Reduce(graph()->NewNode(common()->Projection(0), add));
r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
ASSERT_TRUE(r.Changed());
EXPECT_EQ(p0, r.replacement());
}
@ -1313,18 +1316,20 @@ TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithZero) {
TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithConstant) {
Node* control = graph()->start();
TRACED_FOREACH(int32_t, x, kInt32Values) {
TRACED_FOREACH(int32_t, y, kInt32Values) {
int32_t z;
Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(),
Int32Constant(x), Int32Constant(y));
Int32Constant(x), Int32Constant(y), control);
Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
Reduction r =
Reduce(graph()->NewNode(common()->Projection(1), add, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsInt32Constant(base::bits::SignedAddOverflow32(x, y, &z)));
r = Reduce(graph()->NewNode(common()->Projection(0), add));
r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsInt32Constant(z));
}
@ -1337,33 +1342,36 @@ TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithConstant) {
TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithZero) {
Node* control = graph()->start();
Node* p0 = Parameter(0);
Node* add =
graph()->NewNode(machine()->Int32SubWithOverflow(), p0, Int32Constant(0));
Node* add = graph()->NewNode(machine()->Int32SubWithOverflow(), p0,
Int32Constant(0), control);
Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsInt32Constant(0));
r = Reduce(graph()->NewNode(common()->Projection(0), add));
r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
ASSERT_TRUE(r.Changed());
EXPECT_EQ(p0, r.replacement());
}
TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithConstant) {
Node* control = graph()->start();
TRACED_FOREACH(int32_t, x, kInt32Values) {
TRACED_FOREACH(int32_t, y, kInt32Values) {
int32_t z;
Node* add = graph()->NewNode(machine()->Int32SubWithOverflow(),
Int32Constant(x), Int32Constant(y));
Int32Constant(x), Int32Constant(y), control);
Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
Reduction r =
Reduce(graph()->NewNode(common()->Projection(1), add, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsInt32Constant(base::bits::SignedSubOverflow32(x, y, &z)));
r = Reduce(graph()->NewNode(common()->Projection(0), add));
r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsInt32Constant(z));
}

View File

@ -208,9 +208,7 @@ const PureOperator kPureOperators[] = {
PURE(Word64Ror, 2, 0, 1), // --
PURE(Word64Equal, 2, 0, 1), // --
PURE(Int32Add, 2, 0, 1), // --
PURE(Int32AddWithOverflow, 2, 0, 2), // --
PURE(Int32Sub, 2, 0, 1), // --
PURE(Int32SubWithOverflow, 2, 0, 2), // --
PURE(Int32Mul, 2, 0, 1), // --
PURE(Int32MulHigh, 2, 0, 1), // --
PURE(Int32Div, 2, 1, 1), // --