Home | History | Annotate | Download | only in compiler
      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 
     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 
     20 ConstantFoldingReducer::~ConstantFoldingReducer() {}
     21 
     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