[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:
parent
76368d0854
commit
00889cc29c
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) \
|
||||
|
@ -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) \
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
|
@ -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()));
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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), // --
|
||||
|
Loading…
Reference in New Issue
Block a user