Commit 3cc4e25c authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Avoid unnecessary minus zero checks for Float64->Tagged.

When we change representation from Float64 to Tagged and we know that
the input value can never be -0, we don't need to bother introducing
the check for -0 during effect/control linearization.

R=jarin@chromium.org

Review-Url: https://codereview.chromium.org/2231963002
Cr-Commit-Position: refs/heads/master@{#38568}
parent c0439051
...@@ -762,6 +762,7 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node, ...@@ -762,6 +762,7 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
EffectControlLinearizer::ValueEffectControl EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node, Node* effect, EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node, Node* effect,
Node* control) { Node* control) {
CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op());
Node* value = node->InputAt(0); Node* value = node->InputAt(0);
Node* value32 = graph()->NewNode(machine()->RoundFloat64ToInt32(), value); Node* value32 = graph()->NewNode(machine()->RoundFloat64ToInt32(), value);
...@@ -774,29 +775,32 @@ EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node, Node* effect, ...@@ -774,29 +775,32 @@ EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node, Node* effect,
Node* vsmi; Node* vsmi;
Node* if_box = graph()->NewNode(common()->IfFalse(), branch_same); Node* if_box = graph()->NewNode(common()->IfFalse(), branch_same);
// Check if {value} is -0. if (mode == CheckForMinusZeroMode::kCheckForMinusZero) {
Node* check_zero = graph()->NewNode(machine()->Word32Equal(), value32, // Check if {value} is -0.
jsgraph()->Int32Constant(0)); Node* check_zero = graph()->NewNode(machine()->Word32Equal(), value32,
Node* branch_zero = graph()->NewNode(common()->Branch(BranchHint::kFalse), jsgraph()->Int32Constant(0));
check_zero, if_smi); Node* branch_zero = graph()->NewNode(common()->Branch(BranchHint::kFalse),
check_zero, if_smi);
Node* if_zero = graph()->NewNode(common()->IfTrue(), branch_zero); Node* if_zero = graph()->NewNode(common()->IfTrue(), branch_zero);
Node* if_notzero = graph()->NewNode(common()->IfFalse(), branch_zero); Node* if_notzero = graph()->NewNode(common()->IfFalse(), branch_zero);
// In case of 0, we need to check the high bits for the IEEE -0 pattern. // In case of 0, we need to check the high bits for the IEEE -0 pattern.
Node* check_negative = graph()->NewNode( Node* check_negative = graph()->NewNode(
machine()->Int32LessThan(), machine()->Int32LessThan(),
graph()->NewNode(machine()->Float64ExtractHighWord32(), value), graph()->NewNode(machine()->Float64ExtractHighWord32(), value),
jsgraph()->Int32Constant(0)); jsgraph()->Int32Constant(0));
Node* branch_negative = graph()->NewNode(common()->Branch(BranchHint::kFalse), Node* branch_negative = graph()->NewNode(
check_negative, if_zero); common()->Branch(BranchHint::kFalse), check_negative, if_zero);
Node* if_negative = graph()->NewNode(common()->IfTrue(), branch_negative); Node* if_negative = graph()->NewNode(common()->IfTrue(), branch_negative);
Node* if_notnegative = graph()->NewNode(common()->IfFalse(), branch_negative); Node* if_notnegative =
graph()->NewNode(common()->IfFalse(), branch_negative);
// We need to create a box for negative 0. // We need to create a box for negative 0.
if_smi = graph()->NewNode(common()->Merge(2), if_notzero, if_notnegative); if_smi = graph()->NewNode(common()->Merge(2), if_notzero, if_notnegative);
if_box = graph()->NewNode(common()->Merge(2), if_box, if_negative); if_box = graph()->NewNode(common()->Merge(2), if_box, if_negative);
}
// On 64-bit machines we can just wrap the 32-bit integer in a smi, for 32-bit // On 64-bit machines we can just wrap the 32-bit integer in a smi, for 32-bit
// machines we need to deal with potential overflow and fallback to boxing. // machines we need to deal with potential overflow and fallback to boxing.
......
...@@ -227,8 +227,10 @@ Node* RepresentationChanger::GetTaggedRepresentationFor( ...@@ -227,8 +227,10 @@ Node* RepresentationChanger::GetTaggedRepresentationFor(
} else if (output_rep == } else if (output_rep ==
MachineRepresentation::kFloat32) { // float32 -> float64 -> tagged MachineRepresentation::kFloat32) { // float32 -> float64 -> tagged
node = InsertChangeFloat32ToFloat64(node); node = InsertChangeFloat32ToFloat64(node);
// TODO(bmeurer): Pass -0 hint to ChangeFloat64ToTagged. op = simplified()->ChangeFloat64ToTagged(
op = simplified()->ChangeFloat64ToTagged(); output_type->Maybe(Type::MinusZero())
? CheckForMinusZeroMode::kCheckForMinusZero
: CheckForMinusZeroMode::kDontCheckForMinusZero);
} else if (output_rep == MachineRepresentation::kFloat64) { } else if (output_rep == MachineRepresentation::kFloat64) {
if (output_type->Is(Type::Signed31())) { // float64 -> int32 -> tagged if (output_type->Is(Type::Signed31())) { // float64 -> int32 -> tagged
node = InsertChangeFloat64ToInt32(node); node = InsertChangeFloat64ToInt32(node);
...@@ -242,8 +244,10 @@ Node* RepresentationChanger::GetTaggedRepresentationFor( ...@@ -242,8 +244,10 @@ Node* RepresentationChanger::GetTaggedRepresentationFor(
node = InsertChangeFloat64ToUint32(node); node = InsertChangeFloat64ToUint32(node);
op = simplified()->ChangeUint32ToTagged(); op = simplified()->ChangeUint32ToTagged();
} else { } else {
// TODO(bmeurer): Pass -0 hint to ChangeFloat64ToTagged. op = simplified()->ChangeFloat64ToTagged(
op = simplified()->ChangeFloat64ToTagged(); output_type->Maybe(Type::MinusZero())
? CheckForMinusZeroMode::kCheckForMinusZero
: CheckForMinusZeroMode::kDontCheckForMinusZero);
} }
} else { } else {
return TypeError(node, output_rep, output_type, return TypeError(node, output_rep, output_type,
......
...@@ -208,7 +208,8 @@ CheckFloat64HoleMode CheckFloat64HoleModeOf(const Operator* op) { ...@@ -208,7 +208,8 @@ CheckFloat64HoleMode CheckFloat64HoleModeOf(const Operator* op) {
} }
CheckForMinusZeroMode CheckMinusZeroModeOf(const Operator* op) { CheckForMinusZeroMode CheckMinusZeroModeOf(const Operator* op) {
DCHECK(op->opcode() == IrOpcode::kCheckedInt32Mul || DCHECK(op->opcode() == IrOpcode::kChangeFloat64ToTagged ||
op->opcode() == IrOpcode::kCheckedInt32Mul ||
op->opcode() == IrOpcode::kCheckedFloat64ToInt32 || op->opcode() == IrOpcode::kCheckedFloat64ToInt32 ||
op->opcode() == IrOpcode::kCheckedTaggedToInt32); op->opcode() == IrOpcode::kCheckedTaggedToInt32);
return OpParameter<CheckForMinusZeroMode>(op); return OpParameter<CheckForMinusZeroMode>(op);
...@@ -395,7 +396,6 @@ NumberOperationHint NumberOperationHintOf(const Operator* op) { ...@@ -395,7 +396,6 @@ NumberOperationHint NumberOperationHintOf(const Operator* op) {
V(ChangeInt31ToTaggedSigned, Operator::kNoProperties, 1, 0) \ V(ChangeInt31ToTaggedSigned, Operator::kNoProperties, 1, 0) \
V(ChangeInt32ToTagged, Operator::kNoProperties, 1, 0) \ V(ChangeInt32ToTagged, Operator::kNoProperties, 1, 0) \
V(ChangeUint32ToTagged, Operator::kNoProperties, 1, 0) \ V(ChangeUint32ToTagged, Operator::kNoProperties, 1, 0) \
V(ChangeFloat64ToTagged, Operator::kNoProperties, 1, 0) \
V(ChangeTaggedToBit, Operator::kNoProperties, 1, 0) \ V(ChangeTaggedToBit, Operator::kNoProperties, 1, 0) \
V(ChangeBitToTagged, Operator::kNoProperties, 1, 0) \ V(ChangeBitToTagged, Operator::kNoProperties, 1, 0) \
V(TruncateTaggedToWord32, Operator::kNoProperties, 1, 0) \ V(TruncateTaggedToWord32, Operator::kNoProperties, 1, 0) \
...@@ -458,6 +458,19 @@ struct SimplifiedOperatorGlobalCache final { ...@@ -458,6 +458,19 @@ struct SimplifiedOperatorGlobalCache final {
CHECKED_OP_LIST(CHECKED) CHECKED_OP_LIST(CHECKED)
#undef CHECKED #undef CHECKED
template <CheckForMinusZeroMode kMode>
struct ChangeFloat64ToTaggedOperator final
: public Operator1<CheckForMinusZeroMode> {
ChangeFloat64ToTaggedOperator()
: Operator1<CheckForMinusZeroMode>(
IrOpcode::kChangeFloat64ToTagged, Operator::kPure,
"ChangeFloat64ToTagged", 1, 0, 0, 1, 0, 0, kMode) {}
};
ChangeFloat64ToTaggedOperator<CheckForMinusZeroMode::kCheckForMinusZero>
kChangeFloat64ToTaggedCheckForMinusZeroOperator;
ChangeFloat64ToTaggedOperator<CheckForMinusZeroMode::kDontCheckForMinusZero>
kChangeFloat64ToTaggedDontCheckForMinusZeroOperator;
template <CheckForMinusZeroMode kMode> template <CheckForMinusZeroMode kMode>
struct CheckedInt32MulOperator final struct CheckedInt32MulOperator final
: public Operator1<CheckForMinusZeroMode> { : public Operator1<CheckForMinusZeroMode> {
...@@ -603,6 +616,18 @@ PURE_OP_LIST(GET_FROM_CACHE) ...@@ -603,6 +616,18 @@ PURE_OP_LIST(GET_FROM_CACHE)
CHECKED_OP_LIST(GET_FROM_CACHE) CHECKED_OP_LIST(GET_FROM_CACHE)
#undef GET_FROM_CACHE #undef GET_FROM_CACHE
const Operator* SimplifiedOperatorBuilder::ChangeFloat64ToTagged(
CheckForMinusZeroMode mode) {
switch (mode) {
case CheckForMinusZeroMode::kCheckForMinusZero:
return &cache_.kChangeFloat64ToTaggedCheckForMinusZeroOperator;
case CheckForMinusZeroMode::kDontCheckForMinusZero:
return &cache_.kChangeFloat64ToTaggedDontCheckForMinusZeroOperator;
}
UNREACHABLE();
return nullptr;
}
const Operator* SimplifiedOperatorBuilder::CheckedInt32Mul( const Operator* SimplifiedOperatorBuilder::CheckedInt32Mul(
CheckForMinusZeroMode mode) { CheckForMinusZeroMode mode) {
switch (mode) { switch (mode) {
......
...@@ -299,7 +299,7 @@ class SimplifiedOperatorBuilder final : public ZoneObject { ...@@ -299,7 +299,7 @@ class SimplifiedOperatorBuilder final : public ZoneObject {
const Operator* ChangeInt31ToTaggedSigned(); const Operator* ChangeInt31ToTaggedSigned();
const Operator* ChangeInt32ToTagged(); const Operator* ChangeInt32ToTagged();
const Operator* ChangeUint32ToTagged(); const Operator* ChangeUint32ToTagged();
const Operator* ChangeFloat64ToTagged(); const Operator* ChangeFloat64ToTagged(CheckForMinusZeroMode);
const Operator* ChangeTaggedToBit(); const Operator* ChangeTaggedToBit();
const Operator* ChangeBitToTagged(); const Operator* ChangeBitToTagged();
const Operator* TruncateTaggedToWord32(); const Operator* TruncateTaggedToWord32();
......
...@@ -97,6 +97,10 @@ const double kNaNs[] = {-std::numeric_limits<double>::quiet_NaN(), ...@@ -97,6 +97,10 @@ const double kNaNs[] = {-std::numeric_limits<double>::quiet_NaN(),
bit_cast<double>(V8_UINT64_C(0x7FFFFFFFFFFFFFFF)), bit_cast<double>(V8_UINT64_C(0x7FFFFFFFFFFFFFFF)),
bit_cast<double>(V8_UINT64_C(0xFFFFFFFFFFFFFFFF))}; bit_cast<double>(V8_UINT64_C(0xFFFFFFFFFFFFFFFF))};
const CheckForMinusZeroMode kCheckForMinusZeroModes[] = {
CheckForMinusZeroMode::kDontCheckForMinusZero,
CheckForMinusZeroMode::kCheckForMinusZero};
} // namespace } // namespace
...@@ -183,21 +187,20 @@ TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToBitWithChangeBitToTagged) { ...@@ -183,21 +187,20 @@ TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToBitWithChangeBitToTagged) {
EXPECT_EQ(param0, reduction.replacement()); EXPECT_EQ(param0, reduction.replacement());
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// ChangeFloat64ToTagged // ChangeFloat64ToTagged
TEST_F(SimplifiedOperatorReducerTest, ChangeFloat64ToTaggedWithConstant) { TEST_F(SimplifiedOperatorReducerTest, ChangeFloat64ToTaggedWithConstant) {
TRACED_FOREACH(double, n, kFloat64Values) { TRACED_FOREACH(CheckForMinusZeroMode, mode, kCheckForMinusZeroModes) {
Reduction reduction = Reduce(graph()->NewNode( TRACED_FOREACH(double, n, kFloat64Values) {
simplified()->ChangeFloat64ToTagged(), Float64Constant(n))); Reduction reduction = Reduce(graph()->NewNode(
ASSERT_TRUE(reduction.Changed()); simplified()->ChangeFloat64ToTagged(mode), Float64Constant(n)));
EXPECT_THAT(reduction.replacement(), IsNumberConstant(BitEq(n))); ASSERT_TRUE(reduction.Changed());
EXPECT_THAT(reduction.replacement(), IsNumberConstant(BitEq(n)));
}
} }
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// ChangeInt32ToTagged // ChangeInt32ToTagged
...@@ -219,14 +222,15 @@ TEST_F(SimplifiedOperatorReducerTest, ChangeInt32ToTaggedWithConstant) { ...@@ -219,14 +222,15 @@ TEST_F(SimplifiedOperatorReducerTest, ChangeInt32ToTaggedWithConstant) {
TEST_F(SimplifiedOperatorReducerTest, TEST_F(SimplifiedOperatorReducerTest,
ChangeTaggedToFloat64WithChangeFloat64ToTagged) { ChangeTaggedToFloat64WithChangeFloat64ToTagged) {
Node* param0 = Parameter(0); Node* param0 = Parameter(0);
Reduction reduction = Reduce(graph()->NewNode( TRACED_FOREACH(CheckForMinusZeroMode, mode, kCheckForMinusZeroModes) {
simplified()->ChangeTaggedToFloat64(), Reduction reduction = Reduce(graph()->NewNode(
graph()->NewNode(simplified()->ChangeFloat64ToTagged(), param0))); simplified()->ChangeTaggedToFloat64(),
ASSERT_TRUE(reduction.Changed()); graph()->NewNode(simplified()->ChangeFloat64ToTagged(mode), param0)));
EXPECT_EQ(param0, reduction.replacement()); ASSERT_TRUE(reduction.Changed());
EXPECT_EQ(param0, reduction.replacement());
}
} }
TEST_F(SimplifiedOperatorReducerTest, TEST_F(SimplifiedOperatorReducerTest,
ChangeTaggedToFloat64WithChangeInt32ToTagged) { ChangeTaggedToFloat64WithChangeInt32ToTagged) {
Node* param0 = Parameter(0); Node* param0 = Parameter(0);
...@@ -272,18 +276,18 @@ TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToFloat64WithNaNConstant) { ...@@ -272,18 +276,18 @@ TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToFloat64WithNaNConstant) {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// ChangeTaggedToInt32 // ChangeTaggedToInt32
TEST_F(SimplifiedOperatorReducerTest, TEST_F(SimplifiedOperatorReducerTest,
ChangeTaggedToInt32WithChangeFloat64ToTagged) { ChangeTaggedToInt32WithChangeFloat64ToTagged) {
Node* param0 = Parameter(0); Node* param0 = Parameter(0);
Reduction reduction = Reduce(graph()->NewNode( TRACED_FOREACH(CheckForMinusZeroMode, mode, kCheckForMinusZeroModes) {
simplified()->ChangeTaggedToInt32(), Reduction reduction = Reduce(graph()->NewNode(
graph()->NewNode(simplified()->ChangeFloat64ToTagged(), param0))); simplified()->ChangeTaggedToInt32(),
ASSERT_TRUE(reduction.Changed()); graph()->NewNode(simplified()->ChangeFloat64ToTagged(mode), param0)));
EXPECT_THAT(reduction.replacement(), IsChangeFloat64ToInt32(param0)); ASSERT_TRUE(reduction.Changed());
EXPECT_THAT(reduction.replacement(), IsChangeFloat64ToInt32(param0));
}
} }
TEST_F(SimplifiedOperatorReducerTest, TEST_F(SimplifiedOperatorReducerTest,
ChangeTaggedToInt32WithChangeInt32ToTagged) { ChangeTaggedToInt32WithChangeInt32ToTagged) {
Node* param0 = Parameter(0); Node* param0 = Parameter(0);
...@@ -298,18 +302,18 @@ TEST_F(SimplifiedOperatorReducerTest, ...@@ -298,18 +302,18 @@ TEST_F(SimplifiedOperatorReducerTest,
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// ChangeTaggedToUint32 // ChangeTaggedToUint32
TEST_F(SimplifiedOperatorReducerTest, TEST_F(SimplifiedOperatorReducerTest,
ChangeTaggedToUint32WithChangeFloat64ToTagged) { ChangeTaggedToUint32WithChangeFloat64ToTagged) {
Node* param0 = Parameter(0); Node* param0 = Parameter(0);
Reduction reduction = Reduce(graph()->NewNode( TRACED_FOREACH(CheckForMinusZeroMode, mode, kCheckForMinusZeroModes) {
simplified()->ChangeTaggedToUint32(), Reduction reduction = Reduce(graph()->NewNode(
graph()->NewNode(simplified()->ChangeFloat64ToTagged(), param0))); simplified()->ChangeTaggedToUint32(),
ASSERT_TRUE(reduction.Changed()); graph()->NewNode(simplified()->ChangeFloat64ToTagged(mode), param0)));
EXPECT_THAT(reduction.replacement(), IsChangeFloat64ToUint32(param0)); ASSERT_TRUE(reduction.Changed());
EXPECT_THAT(reduction.replacement(), IsChangeFloat64ToUint32(param0));
}
} }
TEST_F(SimplifiedOperatorReducerTest, TEST_F(SimplifiedOperatorReducerTest,
ChangeTaggedToUint32WithChangeUint32ToTagged) { ChangeTaggedToUint32WithChangeUint32ToTagged) {
Node* param0 = Parameter(0); Node* param0 = Parameter(0);
...@@ -327,11 +331,13 @@ TEST_F(SimplifiedOperatorReducerTest, ...@@ -327,11 +331,13 @@ TEST_F(SimplifiedOperatorReducerTest,
TEST_F(SimplifiedOperatorReducerTest, TEST_F(SimplifiedOperatorReducerTest,
TruncateTaggedToWord3WithChangeFloat64ToTagged) { TruncateTaggedToWord3WithChangeFloat64ToTagged) {
Node* param0 = Parameter(0); Node* param0 = Parameter(0);
Reduction reduction = Reduce(graph()->NewNode( TRACED_FOREACH(CheckForMinusZeroMode, mode, kCheckForMinusZeroModes) {
simplified()->TruncateTaggedToWord32(), Reduction reduction = Reduce(graph()->NewNode(
graph()->NewNode(simplified()->ChangeFloat64ToTagged(), param0))); simplified()->TruncateTaggedToWord32(),
ASSERT_TRUE(reduction.Changed()); graph()->NewNode(simplified()->ChangeFloat64ToTagged(mode), param0)));
EXPECT_THAT(reduction.replacement(), IsTruncateFloat64ToWord32(param0)); ASSERT_TRUE(reduction.Changed());
EXPECT_THAT(reduction.replacement(), IsTruncateFloat64ToWord32(param0));
}
} }
TEST_F(SimplifiedOperatorReducerTest, TruncateTaggedToWord32WithConstant) { TEST_F(SimplifiedOperatorReducerTest, TruncateTaggedToWord32WithConstant) {
......
...@@ -60,7 +60,6 @@ const PureOperator kPureOperators[] = { ...@@ -60,7 +60,6 @@ const PureOperator kPureOperators[] = {
PURE(ChangeTaggedToFloat64, Operator::kNoProperties, 1), PURE(ChangeTaggedToFloat64, Operator::kNoProperties, 1),
PURE(ChangeInt32ToTagged, Operator::kNoProperties, 1), PURE(ChangeInt32ToTagged, Operator::kNoProperties, 1),
PURE(ChangeUint32ToTagged, Operator::kNoProperties, 1), PURE(ChangeUint32ToTagged, Operator::kNoProperties, 1),
PURE(ChangeFloat64ToTagged, Operator::kNoProperties, 1),
PURE(ChangeTaggedToBit, Operator::kNoProperties, 1), PURE(ChangeTaggedToBit, Operator::kNoProperties, 1),
PURE(ChangeBitToTagged, Operator::kNoProperties, 1), PURE(ChangeBitToTagged, Operator::kNoProperties, 1),
PURE(TruncateTaggedToWord32, Operator::kNoProperties, 1), PURE(TruncateTaggedToWord32, Operator::kNoProperties, 1),
......
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