1 // Copyright 2018 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/compiler/constant-folding-reducer.h"
6
7 #include "src/compiler/js-graph.h"
8 #include "src/objects-inl.h"
9
10 namespace v8 {
11 namespace internal {
12 namespace compiler {
13
ConstantFoldingReducer(Editor * editor,JSGraph * jsgraph,JSHeapBroker * js_heap_broker)14 ConstantFoldingReducer::ConstantFoldingReducer(Editor* editor, JSGraph* jsgraph,
15 JSHeapBroker* js_heap_broker)
16 : AdvancedReducer(editor),
17 jsgraph_(jsgraph),
18 js_heap_broker_(js_heap_broker) {}
19
~ConstantFoldingReducer()20 ConstantFoldingReducer::~ConstantFoldingReducer() {}
21
Reduce(Node * node)22 Reduction ConstantFoldingReducer::Reduce(Node* node) {
23 DisallowHeapAccess no_heap_access;
24 // Check if the output type is a singleton. In that case we already know the
25 // result value and can simply replace the node if it's eliminable.
26 if (!NodeProperties::IsConstant(node) && NodeProperties::IsTyped(node) &&
27 node->op()->HasProperty(Operator::kEliminatable)) {
28 // TODO(v8:5303): We must not eliminate FinishRegion here. This special
29 // case can be removed once we have separate operators for value and
30 // effect regions.
31 if (node->opcode() == IrOpcode::kFinishRegion) return NoChange();
32 // We can only constant-fold nodes here, that are known to not cause any
33 // side-effect, may it be a JavaScript observable side-effect or a possible
34 // eager deoptimization exit (i.e. {node} has an operator that doesn't have
35 // the Operator::kNoDeopt property).
36 Type upper = NodeProperties::GetType(node);
37 if (!upper.IsNone()) {
38 Node* replacement = nullptr;
39 if (upper.IsHeapConstant()) {
40 replacement = jsgraph()->Constant(upper.AsHeapConstant()->Ref());
41 } else if (upper.Is(Type::MinusZero())) {
42 Factory* factory = jsgraph()->isolate()->factory();
43 ObjectRef minus_zero(js_heap_broker(), factory->minus_zero_value());
44 replacement = jsgraph()->Constant(minus_zero);
45 } else if (upper.Is(Type::NaN())) {
46 replacement = jsgraph()->NaNConstant();
47 } else if (upper.Is(Type::Null())) {
48 replacement = jsgraph()->NullConstant();
49 } else if (upper.Is(Type::PlainNumber()) && upper.Min() == upper.Max()) {
50 replacement = jsgraph()->Constant(upper.Min());
51 } else if (upper.Is(Type::Undefined())) {
52 replacement = jsgraph()->UndefinedConstant();
53 }
54 if (replacement) {
55 // Make sure the node has a type.
56 if (!NodeProperties::IsTyped(replacement)) {
57 NodeProperties::SetType(replacement, upper);
58 }
59 ReplaceWithValue(node, replacement);
60 return Changed(replacement);
61 }
62 }
63 }
64 return NoChange();
65 }
66
67 } // namespace compiler
68 } // namespace internal
69 } // namespace v8
70