[turbofan] Fix inconsistent typing of NumberFloor(NumberDivide(...))
In typed-optimization, Turbofan optimized NumberFloor(NumberDivide(...)) patterns where both inputs are known to be of Unsigned32 type, but the replacement couldn't be typed consistently. This CL introduces a new operator Unsigned32Divide, which has the same semantics, but can be typed consistently and thus allows the simplified lowering verifier to validate the graph correctly. Bug: v8:12619 Change-Id: Iad77154d3d840c94edfd3ab91ffa37c840da0bc9 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3644790 Commit-Queue: Nico Hartmann <nicohartmann@chromium.org> Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/main@{#80967}
This commit is contained in:
parent
e50d19cb11
commit
46ed47e66a
@ -493,6 +493,7 @@
|
||||
V(TransitionAndStoreNumberElement) \
|
||||
V(TransitionElementsKind) \
|
||||
V(TypeOf) \
|
||||
V(Unsigned32Divide) \
|
||||
V(VerifyType)
|
||||
|
||||
#define SIMPLIFIED_SPECULATIVE_BIGINT_BINOP_LIST(V) \
|
||||
|
@ -767,7 +767,7 @@ class RepresentationSelector {
|
||||
TurboJsonFile json_of(info, std::ios_base::app);
|
||||
JSONGraphWriter writer(json_of, graph(), source_positions_,
|
||||
node_origins_);
|
||||
writer.PrintPhase("V8.TFSimplifiedLowering [after retype]");
|
||||
writer.PrintPhase("V8.TFSimplifiedLowering [after lower]");
|
||||
}
|
||||
|
||||
// Verify all nodes.
|
||||
@ -797,7 +797,6 @@ class RepresentationSelector {
|
||||
RunPropagatePhase();
|
||||
RunRetypePhase();
|
||||
RunLowerPhase(lowering);
|
||||
|
||||
if (verification_enabled()) {
|
||||
RunVerifyPhase(lowering->info_);
|
||||
}
|
||||
@ -2582,6 +2581,14 @@ class RepresentationSelector {
|
||||
if (lower<T>()) ChangeToPureOp(node, Float64Op(node));
|
||||
return;
|
||||
}
|
||||
case IrOpcode::kUnsigned32Divide: {
|
||||
CHECK(TypeOf(node->InputAt(0)).Is(Type::Unsigned32()));
|
||||
CHECK(TypeOf(node->InputAt(1)).Is(Type::Unsigned32()));
|
||||
// => unsigned Uint32Div
|
||||
VisitWord32TruncatingBinop<T>(node);
|
||||
if (lower<T>()) DeferReplacement(node, lowering->Uint32Div(node));
|
||||
return;
|
||||
}
|
||||
case IrOpcode::kSpeculativeNumberModulus:
|
||||
return VisitSpeculativeNumberModulus<T>(node, truncation, lowering);
|
||||
case IrOpcode::kNumberModulus: {
|
||||
|
@ -799,7 +799,8 @@ bool operator==(CheckMinusZeroParameters const& lhs,
|
||||
V(StringLessThan, Operator::kNoProperties, 2, 0) \
|
||||
V(StringLessThanOrEqual, Operator::kNoProperties, 2, 0) \
|
||||
V(ToBoolean, Operator::kNoProperties, 1, 0) \
|
||||
V(NewConsString, Operator::kNoProperties, 3, 0)
|
||||
V(NewConsString, Operator::kNoProperties, 3, 0) \
|
||||
V(Unsigned32Divide, Operator::kNoProperties, 2, 0)
|
||||
|
||||
#define EFFECT_DEPENDENT_OP_LIST(V) \
|
||||
V(BigIntAdd, Operator::kNoProperties, 2, 1) \
|
||||
|
@ -1072,6 +1072,11 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
|
||||
#endif
|
||||
|
||||
const Operator* DateNow();
|
||||
// Unsigned32Divide is a special operator to express the division of two
|
||||
// Unsigned32 inputs and truncating the result to Unsigned32. It's semantics
|
||||
// is equivalent to NumberFloor(NumberDivide(x:Unsigned32, y:Unsigned32)) but
|
||||
// is required to allow consistent typing of the graph.
|
||||
const Operator* Unsigned32Divide();
|
||||
|
||||
// Represents the inputs necessary to construct a fast and a slow API call.
|
||||
const Operator* FastApiCall(
|
||||
|
@ -328,16 +328,14 @@ Reduction TypedOptimization::ReduceNumberFloor(Node* node) {
|
||||
//
|
||||
// with
|
||||
//
|
||||
// NumberToUint32(NumberDivide(lhs, rhs))
|
||||
// Unsigned32Divide(lhs, rhs)
|
||||
//
|
||||
// and just smash the type [0...lhs.Max] on the {node},
|
||||
// and have the new node typed to [0...lhs.Max],
|
||||
// as the truncated result must be lower than {lhs}'s maximum
|
||||
// value (note that {rhs} cannot be less than 1 due to the
|
||||
// plain-number type constraint on the {node}).
|
||||
NodeProperties::ChangeOp(node, simplified()->NumberToUint32());
|
||||
NodeProperties::SetType(node,
|
||||
Type::Range(0, lhs_type.Max(), graph()->zone()));
|
||||
return Changed(node);
|
||||
node = graph()->NewNode(simplified()->Unsigned32Divide(), lhs, rhs);
|
||||
return Replace(node);
|
||||
}
|
||||
}
|
||||
return NoChange();
|
||||
|
@ -1525,6 +1525,11 @@ Type Typer::Visitor::TypeJSObjectIsArray(Node* node) { return Type::Boolean(); }
|
||||
|
||||
Type Typer::Visitor::TypeDateNow(Node* node) { return Type::Number(); }
|
||||
|
||||
Type Typer::Visitor::TypeUnsigned32Divide(Node* node) {
|
||||
Type lhs = Operand(node, 0);
|
||||
return Type::Range(0, lhs.Max(), zone());
|
||||
}
|
||||
|
||||
Type Typer::Visitor::JSCallTyper(Type fun, Typer* t) {
|
||||
if (!fun.IsHeapConstant() || !fun.AsHeapConstant()->Ref().IsJSFunction()) {
|
||||
return Type::NonInternal();
|
||||
|
@ -1096,6 +1096,11 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
|
||||
CheckValueInputIs(node, 0, Type::Number());
|
||||
CheckTypeIs(node, Type::Unsigned32());
|
||||
break;
|
||||
case IrOpcode::kUnsigned32Divide:
|
||||
CheckValueInputIs(node, 0, Type::Unsigned32());
|
||||
CheckValueInputIs(node, 1, Type::Unsigned32());
|
||||
CheckTypeIs(node, Type::Unsigned32());
|
||||
break;
|
||||
case IrOpcode::kSpeculativeToNumber:
|
||||
CheckValueInputIs(node, 0, Type::Any());
|
||||
CheckTypeIs(node, Type::Number());
|
||||
|
20
test/mjsunit/regress/regress-1323602.js
Normal file
20
test/mjsunit/regress/regress-1323602.js
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax --turbofan
|
||||
|
||||
let g;
|
||||
|
||||
function test() {
|
||||
const ten = 10;
|
||||
const x = 10 / ten;
|
||||
const y = Math.floor(x);
|
||||
g = x;
|
||||
return y + 1;
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(test);
|
||||
assertEquals(2, test());
|
||||
%OptimizeFunctionOnNextCall(test);
|
||||
assertEquals(2, test());
|
Loading…
Reference in New Issue
Block a user