Commit 2c834c53 authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

[turbofan] Clean up ConstantFoldingReducer

Change-Id: Iaf7f83cc157a6f6680da8933560347f7f3503d56
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2098736Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66706}
parent 7eeb5380
...@@ -11,6 +11,36 @@ namespace v8 { ...@@ -11,6 +11,36 @@ namespace v8 {
namespace internal { namespace internal {
namespace compiler { namespace compiler {
namespace {
Node* TryGetConstant(JSGraph* jsgraph, Node* node) {
Type type = NodeProperties::GetType(node);
Node* result;
if (type.IsNone()) {
result = nullptr;
} else if (type.Is(Type::Null())) {
result = jsgraph->NullConstant();
} else if (type.Is(Type::Undefined())) {
result = jsgraph->UndefinedConstant();
} else if (type.Is(Type::MinusZero())) {
result = jsgraph->MinusZeroConstant();
} else if (type.Is(Type::NaN())) {
result = jsgraph->NaNConstant();
} else if (type.Is(Type::Hole())) {
result = jsgraph->TheHoleConstant();
} else if (type.IsHeapConstant()) {
result = jsgraph->Constant(type.AsHeapConstant()->Ref());
} else if (type.Is(Type::PlainNumber()) && type.Min() == type.Max()) {
result = jsgraph->Constant(type.Min());
} else {
result = nullptr;
}
DCHECK_EQ(result != nullptr, type.IsSingleton());
DCHECK_IMPLIES(result != nullptr,
NodeProperties::GetType(result).Equals(type));
return result;
}
} // namespace
ConstantFoldingReducer::ConstantFoldingReducer(Editor* editor, JSGraph* jsgraph, ConstantFoldingReducer::ConstantFoldingReducer(Editor* editor, JSGraph* jsgraph,
JSHeapBroker* broker) JSHeapBroker* broker)
: AdvancedReducer(editor), jsgraph_(jsgraph), broker_(broker) {} : AdvancedReducer(editor), jsgraph_(jsgraph), broker_(broker) {}
...@@ -19,44 +49,15 @@ ConstantFoldingReducer::~ConstantFoldingReducer() = default; ...@@ -19,44 +49,15 @@ ConstantFoldingReducer::~ConstantFoldingReducer() = default;
Reduction ConstantFoldingReducer::Reduce(Node* node) { Reduction ConstantFoldingReducer::Reduce(Node* node) {
DisallowHeapAccess no_heap_access; DisallowHeapAccess no_heap_access;
// Check if the output type is a singleton. In that case we already know the
// result value and can simply replace the node if it's eliminable.
if (!NodeProperties::IsConstant(node) && NodeProperties::IsTyped(node) && if (!NodeProperties::IsConstant(node) && NodeProperties::IsTyped(node) &&
node->op()->HasProperty(Operator::kEliminatable)) { node->opcode() != IrOpcode::kFinishRegion) {
// TODO(v8:5303): We must not eliminate FinishRegion here. This special Node* constant = TryGetConstant(jsgraph(), node);
// case can be removed once we have separate operators for value and if (constant != nullptr) {
// effect regions. if (node->op()->HasProperty(Operator::kEliminatable)) {
if (node->opcode() == IrOpcode::kFinishRegion) return NoChange(); RelaxEffectsAndControls(node);
// We can only constant-fold nodes here, that are known to not cause any
// side-effect, may it be a JavaScript observable side-effect or a possible
// eager deoptimization exit (i.e. {node} has an operator that doesn't have
// the Operator::kNoDeopt property).
Type upper = NodeProperties::GetType(node);
if (!upper.IsNone()) {
Node* replacement = nullptr;
if (upper.IsHeapConstant()) {
replacement = jsgraph()->Constant(upper.AsHeapConstant()->Ref());
} else if (upper.Is(Type::MinusZero())) {
Factory* factory = jsgraph()->isolate()->factory();
ObjectRef minus_zero(broker(), factory->minus_zero_value());
replacement = jsgraph()->Constant(minus_zero);
} else if (upper.Is(Type::NaN())) {
replacement = jsgraph()->NaNConstant();
} else if (upper.Is(Type::Null())) {
replacement = jsgraph()->NullConstant();
} else if (upper.Is(Type::PlainNumber()) && upper.Min() == upper.Max()) {
replacement = jsgraph()->Constant(upper.Min());
} else if (upper.Is(Type::Undefined())) {
replacement = jsgraph()->UndefinedConstant();
}
if (replacement) {
// Make sure the node has a type.
if (!NodeProperties::IsTyped(replacement)) {
NodeProperties::SetType(replacement, upper);
}
ReplaceWithValue(node, replacement);
return Changed(replacement);
} }
ReplaceWithValue(node, constant, node, node);
return Changed(node);
} }
} }
return NoChange(); return NoChange();
......
...@@ -160,6 +160,8 @@ DEFINE_GETTER(NullConstant, HeapConstant(factory()->null_value())) ...@@ -160,6 +160,8 @@ DEFINE_GETTER(NullConstant, HeapConstant(factory()->null_value()))
DEFINE_GETTER(ZeroConstant, NumberConstant(0.0)) DEFINE_GETTER(ZeroConstant, NumberConstant(0.0))
DEFINE_GETTER(MinusZeroConstant, NumberConstant(-0.0))
DEFINE_GETTER(OneConstant, NumberConstant(1.0)) DEFINE_GETTER(OneConstant, NumberConstant(1.0))
DEFINE_GETTER(MinusOneConstant, NumberConstant(-1.0)) DEFINE_GETTER(MinusOneConstant, NumberConstant(-1.0))
......
...@@ -99,9 +99,10 @@ class V8_EXPORT_PRIVATE JSGraph : public MachineGraph { ...@@ -99,9 +99,10 @@ class V8_EXPORT_PRIVATE JSGraph : public MachineGraph {
V(FalseConstant) \ V(FalseConstant) \
V(NullConstant) \ V(NullConstant) \
V(ZeroConstant) \ V(ZeroConstant) \
V(MinusZeroConstant) \
V(OneConstant) \ V(OneConstant) \
V(NaNConstant) \
V(MinusOneConstant) \ V(MinusOneConstant) \
V(NaNConstant) \
V(EmptyStateValues) \ V(EmptyStateValues) \
V(SingleDeadTypedStateValues) V(SingleDeadTypedStateValues)
......
...@@ -80,6 +80,12 @@ class ConstantFoldingReducerTest : public TypedGraphTest { ...@@ -80,6 +80,12 @@ class ConstantFoldingReducerTest : public TypedGraphTest {
return reducer.Reduce(node); return reducer.Reduce(node);
} }
Node* UseValue(Node* node) {
Node* start = graph()->NewNode(common()->Start(1));
Node* zero = graph()->NewNode(common()->NumberConstant(0));
return graph()->NewNode(common()->Return(), zero, node, start, start);
}
SimplifiedOperatorBuilder* simplified() { return &simplified_; } SimplifiedOperatorBuilder* simplified() { return &simplified_; }
JSHeapBroker* broker() { return &broker_; } JSHeapBroker* broker() { return &broker_; }
...@@ -91,20 +97,26 @@ class ConstantFoldingReducerTest : public TypedGraphTest { ...@@ -91,20 +97,26 @@ class ConstantFoldingReducerTest : public TypedGraphTest {
TEST_F(ConstantFoldingReducerTest, ParameterWithMinusZero) { TEST_F(ConstantFoldingReducerTest, ParameterWithMinusZero) {
{ {
Reduction r = Reduce(Parameter( Node* node = Parameter(
Type::Constant(broker(), factory()->minus_zero_value(), zone()))); Type::Constant(broker(), factory()->minus_zero_value(), zone()));
Node* use_value = UseValue(node);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(-0.0)); EXPECT_THAT(use_value->InputAt(1), IsNumberConstant(-0.0));
} }
{ {
Reduction r = Reduce(Parameter(Type::MinusZero())); Node* node = Parameter(Type::MinusZero());
Node* use_value = UseValue(node);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(-0.0)); EXPECT_THAT(use_value->InputAt(1), IsNumberConstant(-0.0));
} }
{ {
Reduction r = Reduce(Parameter(Type::Union( Node* node = Parameter(Type::Union(
Type::MinusZero(), Type::MinusZero(),
Type::Constant(broker(), factory()->NewNumber(0), zone()), zone()))); Type::Constant(broker(), factory()->NewNumber(0), zone()), zone()));
UseValue(node);
Reduction r = Reduce(node);
EXPECT_FALSE(r.Changed()); EXPECT_FALSE(r.Changed());
} }
} }
...@@ -112,14 +124,18 @@ TEST_F(ConstantFoldingReducerTest, ParameterWithMinusZero) { ...@@ -112,14 +124,18 @@ TEST_F(ConstantFoldingReducerTest, ParameterWithMinusZero) {
TEST_F(ConstantFoldingReducerTest, ParameterWithNull) { TEST_F(ConstantFoldingReducerTest, ParameterWithNull) {
Handle<HeapObject> null = factory()->null_value(); Handle<HeapObject> null = factory()->null_value();
{ {
Reduction r = Reduce(Parameter(Type::Constant(broker(), null, zone()))); Node* node = Parameter(Type::Constant(broker(), null, zone()));
Node* use_value = UseValue(node);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsHeapConstant(null)); EXPECT_THAT(use_value->InputAt(1), IsHeapConstant(null));
} }
{ {
Reduction r = Reduce(Parameter(Type::Null())); Node* node = Parameter(Type::Null());
Node* use_value = UseValue(node);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsHeapConstant(null)); EXPECT_THAT(use_value->InputAt(1), IsHeapConstant(null));
} }
} }
...@@ -129,49 +145,62 @@ TEST_F(ConstantFoldingReducerTest, ParameterWithNaN) { ...@@ -129,49 +145,62 @@ TEST_F(ConstantFoldingReducerTest, ParameterWithNaN) {
std::numeric_limits<double>::signaling_NaN()}; std::numeric_limits<double>::signaling_NaN()};
TRACED_FOREACH(double, nan, kNaNs) { TRACED_FOREACH(double, nan, kNaNs) {
Handle<Object> constant = factory()->NewNumber(nan); Handle<Object> constant = factory()->NewNumber(nan);
Reduction r = Reduce(Parameter(Type::Constant(broker(), constant, zone()))); Node* node = Parameter(Type::Constant(broker(), constant, zone()));
Node* use_value = UseValue(node);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN())); EXPECT_THAT(use_value->InputAt(1), IsNumberConstant(IsNaN()));
} }
{ {
Reduction r = Reduce( Node* node =
Parameter(Type::Constant(broker(), factory()->nan_value(), zone()))); Parameter(Type::Constant(broker(), factory()->nan_value(), zone()));
Node* use_value = UseValue(node);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN())); EXPECT_THAT(use_value->InputAt(1), IsNumberConstant(IsNaN()));
} }
{ {
Reduction r = Reduce(Parameter(Type::NaN())); Node* node = Parameter(Type::NaN());
Node* use_value = UseValue(node);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN())); EXPECT_THAT(use_value->InputAt(1), IsNumberConstant(IsNaN()));
} }
} }
TEST_F(ConstantFoldingReducerTest, ParameterWithPlainNumber) { TEST_F(ConstantFoldingReducerTest, ParameterWithPlainNumber) {
TRACED_FOREACH(double, value, kFloat64Values) { TRACED_FOREACH(double, value, kFloat64Values) {
Handle<Object> constant = factory()->NewNumber(value); Handle<Object> constant = factory()->NewNumber(value);
Reduction r = Reduce(Parameter(Type::Constant(broker(), constant, zone()))); Node* node = Parameter(Type::Constant(broker(), constant, zone()));
Node* use_value = UseValue(node);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(value)); EXPECT_THAT(use_value->InputAt(1), IsNumberConstant(value));
} }
TRACED_FOREACH(double, value, kIntegerValues) { TRACED_FOREACH(double, value, kIntegerValues) {
Reduction r = Reduce(Parameter(Type::Range(value, value, zone()))); Node* node = Parameter(Type::Range(value, value, zone()));
Node* use_value = UseValue(node);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(value)); EXPECT_THAT(use_value->InputAt(1), IsNumberConstant(value));
} }
} }
TEST_F(ConstantFoldingReducerTest, ParameterWithUndefined) { TEST_F(ConstantFoldingReducerTest, ParameterWithUndefined) {
Handle<HeapObject> undefined = factory()->undefined_value(); Handle<HeapObject> undefined = factory()->undefined_value();
{ {
Reduction r = Reduce(Parameter(Type::Undefined())); Node* node = Parameter(Type::Undefined());
Node* use_value = UseValue(node);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsHeapConstant(undefined)); EXPECT_THAT(use_value->InputAt(1), IsUndefinedConstant());
} }
{ {
Reduction r = Node* node = Parameter(Type::Constant(broker(), undefined, zone()));
Reduce(Parameter(Type::Constant(broker(), undefined, zone()))); Node* use_value = UseValue(node);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsHeapConstant(undefined)); EXPECT_THAT(use_value->InputAt(1), IsUndefinedConstant());
} }
} }
...@@ -200,9 +229,11 @@ TEST_F(ConstantFoldingReducerTest, ToBooleanWithFalsish) { ...@@ -200,9 +229,11 @@ TEST_F(ConstantFoldingReducerTest, ToBooleanWithFalsish) {
zone()), zone()),
zone()), zone()),
0); 0);
Reduction r = Reduce(graph()->NewNode(simplified()->ToBoolean(), input)); Node* node = graph()->NewNode(simplified()->ToBoolean(), input);
Node* use_value = UseValue(node);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsFalseConstant()); EXPECT_THAT(use_value->InputAt(1), IsFalseConstant());
} }
TEST_F(ConstantFoldingReducerTest, ToBooleanWithTruish) { TEST_F(ConstantFoldingReducerTest, ToBooleanWithTruish) {
...@@ -212,16 +243,20 @@ TEST_F(ConstantFoldingReducerTest, ToBooleanWithTruish) { ...@@ -212,16 +243,20 @@ TEST_F(ConstantFoldingReducerTest, ToBooleanWithTruish) {
Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone()), Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone()),
zone()), zone()),
0); 0);
Reduction r = Reduce(graph()->NewNode(simplified()->ToBoolean(), input)); Node* node = graph()->NewNode(simplified()->ToBoolean(), input);
Node* use_value = UseValue(node);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsTrueConstant()); EXPECT_THAT(use_value->InputAt(1), IsTrueConstant());
} }
TEST_F(ConstantFoldingReducerTest, ToBooleanWithNonZeroPlainNumber) { TEST_F(ConstantFoldingReducerTest, ToBooleanWithNonZeroPlainNumber) {
Node* input = Parameter(Type::Range(1, V8_INFINITY, zone()), 0); Node* input = Parameter(Type::Range(1, V8_INFINITY, zone()), 0);
Reduction r = Reduce(graph()->NewNode(simplified()->ToBoolean(), input)); Node* node = graph()->NewNode(simplified()->ToBoolean(), input);
Node* use_value = UseValue(node);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsTrueConstant()); EXPECT_THAT(use_value->InputAt(1), IsTrueConstant());
} }
} // namespace constant_folding_reducer_unittest } // namespace constant_folding_reducer_unittest
......
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