11cb0ef41Sopenharmony_ci// Copyright 2018 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/compiler/constant-folding-reducer.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include "src/compiler/js-graph.h" 81cb0ef41Sopenharmony_ci#include "src/compiler/js-heap-broker.h" 91cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h" 101cb0ef41Sopenharmony_ci 111cb0ef41Sopenharmony_cinamespace v8 { 121cb0ef41Sopenharmony_cinamespace internal { 131cb0ef41Sopenharmony_cinamespace compiler { 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_cinamespace { 161cb0ef41Sopenharmony_ciNode* TryGetConstant(JSGraph* jsgraph, Node* node) { 171cb0ef41Sopenharmony_ci Type type = NodeProperties::GetType(node); 181cb0ef41Sopenharmony_ci Node* result; 191cb0ef41Sopenharmony_ci if (type.IsNone()) { 201cb0ef41Sopenharmony_ci result = nullptr; 211cb0ef41Sopenharmony_ci } else if (type.Is(Type::Null())) { 221cb0ef41Sopenharmony_ci result = jsgraph->NullConstant(); 231cb0ef41Sopenharmony_ci } else if (type.Is(Type::Undefined())) { 241cb0ef41Sopenharmony_ci result = jsgraph->UndefinedConstant(); 251cb0ef41Sopenharmony_ci } else if (type.Is(Type::MinusZero())) { 261cb0ef41Sopenharmony_ci result = jsgraph->MinusZeroConstant(); 271cb0ef41Sopenharmony_ci } else if (type.Is(Type::NaN())) { 281cb0ef41Sopenharmony_ci result = jsgraph->NaNConstant(); 291cb0ef41Sopenharmony_ci } else if (type.Is(Type::Hole())) { 301cb0ef41Sopenharmony_ci result = jsgraph->TheHoleConstant(); 311cb0ef41Sopenharmony_ci } else if (type.IsHeapConstant()) { 321cb0ef41Sopenharmony_ci result = jsgraph->Constant(type.AsHeapConstant()->Ref()); 331cb0ef41Sopenharmony_ci } else if (type.Is(Type::PlainNumber()) && type.Min() == type.Max()) { 341cb0ef41Sopenharmony_ci result = jsgraph->Constant(type.Min()); 351cb0ef41Sopenharmony_ci } else { 361cb0ef41Sopenharmony_ci result = nullptr; 371cb0ef41Sopenharmony_ci } 381cb0ef41Sopenharmony_ci DCHECK_EQ(result != nullptr, type.IsSingleton()); 391cb0ef41Sopenharmony_ci DCHECK_IMPLIES(result != nullptr, 401cb0ef41Sopenharmony_ci type.Equals(NodeProperties::GetType(result))); 411cb0ef41Sopenharmony_ci return result; 421cb0ef41Sopenharmony_ci} 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_cibool IsAlreadyBeingFolded(Node* node) { 451cb0ef41Sopenharmony_ci DCHECK(FLAG_assert_types); 461cb0ef41Sopenharmony_ci if (node->opcode() == IrOpcode::kFoldConstant) return true; 471cb0ef41Sopenharmony_ci for (Edge edge : node->use_edges()) { 481cb0ef41Sopenharmony_ci if (NodeProperties::IsValueEdge(edge) && 491cb0ef41Sopenharmony_ci edge.from()->opcode() == IrOpcode::kFoldConstant) { 501cb0ef41Sopenharmony_ci // Note: {node} may have gained new value uses since the time it was 511cb0ef41Sopenharmony_ci // "constant-folded", and theses uses should ideally be rewritten as well. 521cb0ef41Sopenharmony_ci // For simplicity, we ignore them here. 531cb0ef41Sopenharmony_ci return true; 541cb0ef41Sopenharmony_ci } 551cb0ef41Sopenharmony_ci } 561cb0ef41Sopenharmony_ci return false; 571cb0ef41Sopenharmony_ci} 581cb0ef41Sopenharmony_ci} // namespace 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ciConstantFoldingReducer::ConstantFoldingReducer(Editor* editor, JSGraph* jsgraph, 611cb0ef41Sopenharmony_ci JSHeapBroker* broker) 621cb0ef41Sopenharmony_ci : AdvancedReducer(editor), jsgraph_(jsgraph), broker_(broker) {} 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ciConstantFoldingReducer::~ConstantFoldingReducer() = default; 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ciReduction ConstantFoldingReducer::Reduce(Node* node) { 671cb0ef41Sopenharmony_ci if (!NodeProperties::IsConstant(node) && NodeProperties::IsTyped(node) && 681cb0ef41Sopenharmony_ci node->op()->HasProperty(Operator::kEliminatable) && 691cb0ef41Sopenharmony_ci node->opcode() != IrOpcode::kFinishRegion) { 701cb0ef41Sopenharmony_ci Node* constant = TryGetConstant(jsgraph(), node); 711cb0ef41Sopenharmony_ci if (constant != nullptr) { 721cb0ef41Sopenharmony_ci DCHECK(NodeProperties::IsTyped(constant)); 731cb0ef41Sopenharmony_ci if (!FLAG_assert_types) { 741cb0ef41Sopenharmony_ci DCHECK_EQ(node->op()->ControlOutputCount(), 0); 751cb0ef41Sopenharmony_ci ReplaceWithValue(node, constant); 761cb0ef41Sopenharmony_ci return Replace(constant); 771cb0ef41Sopenharmony_ci } else if (!IsAlreadyBeingFolded(node)) { 781cb0ef41Sopenharmony_ci // Delay the constant folding (by inserting a FoldConstant operation 791cb0ef41Sopenharmony_ci // instead) in order to keep type assertions meaningful. 801cb0ef41Sopenharmony_ci Node* fold_constant = jsgraph()->graph()->NewNode( 811cb0ef41Sopenharmony_ci jsgraph()->common()->FoldConstant(), node, constant); 821cb0ef41Sopenharmony_ci DCHECK(NodeProperties::IsTyped(fold_constant)); 831cb0ef41Sopenharmony_ci ReplaceWithValue(node, fold_constant, node, node); 841cb0ef41Sopenharmony_ci fold_constant->ReplaceInput(0, node); 851cb0ef41Sopenharmony_ci DCHECK(IsAlreadyBeingFolded(node)); 861cb0ef41Sopenharmony_ci DCHECK(IsAlreadyBeingFolded(fold_constant)); 871cb0ef41Sopenharmony_ci return Changed(node); 881cb0ef41Sopenharmony_ci } 891cb0ef41Sopenharmony_ci } 901cb0ef41Sopenharmony_ci } 911cb0ef41Sopenharmony_ci return NoChange(); 921cb0ef41Sopenharmony_ci} 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_ci} // namespace compiler 951cb0ef41Sopenharmony_ci} // namespace internal 961cb0ef41Sopenharmony_ci} // namespace v8 97