11cb0ef41Sopenharmony_ci// Copyright 2016 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/load-elimination.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include "src/compiler/access-builder.h"
81cb0ef41Sopenharmony_ci#include "src/compiler/common-operator.h"
91cb0ef41Sopenharmony_ci#include "src/compiler/js-graph.h"
101cb0ef41Sopenharmony_ci#include "src/compiler/node-properties.h"
111cb0ef41Sopenharmony_ci#include "src/heap/factory.h"
121cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h"
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_cinamespace v8 {
151cb0ef41Sopenharmony_cinamespace internal {
161cb0ef41Sopenharmony_cinamespace compiler {
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_cinamespace {
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_cibool IsRename(Node* node) {
211cb0ef41Sopenharmony_ci  switch (node->opcode()) {
221cb0ef41Sopenharmony_ci    case IrOpcode::kCheckHeapObject:
231cb0ef41Sopenharmony_ci    case IrOpcode::kFinishRegion:
241cb0ef41Sopenharmony_ci    case IrOpcode::kTypeGuard:
251cb0ef41Sopenharmony_ci      return !node->IsDead();
261cb0ef41Sopenharmony_ci    default:
271cb0ef41Sopenharmony_ci      return false;
281cb0ef41Sopenharmony_ci  }
291cb0ef41Sopenharmony_ci}
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ciNode* ResolveRenames(Node* node) {
321cb0ef41Sopenharmony_ci  while (IsRename(node)) {
331cb0ef41Sopenharmony_ci    node = node->InputAt(0);
341cb0ef41Sopenharmony_ci  }
351cb0ef41Sopenharmony_ci  return node;
361cb0ef41Sopenharmony_ci}
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_cibool MayAlias(Node* a, Node* b) {
391cb0ef41Sopenharmony_ci  if (a != b) {
401cb0ef41Sopenharmony_ci    if (!NodeProperties::GetType(a).Maybe(NodeProperties::GetType(b))) {
411cb0ef41Sopenharmony_ci      return false;
421cb0ef41Sopenharmony_ci    } else if (IsRename(b)) {
431cb0ef41Sopenharmony_ci      return MayAlias(a, b->InputAt(0));
441cb0ef41Sopenharmony_ci    } else if (IsRename(a)) {
451cb0ef41Sopenharmony_ci      return MayAlias(a->InputAt(0), b);
461cb0ef41Sopenharmony_ci    } else if (b->opcode() == IrOpcode::kAllocate) {
471cb0ef41Sopenharmony_ci      switch (a->opcode()) {
481cb0ef41Sopenharmony_ci        case IrOpcode::kAllocate:
491cb0ef41Sopenharmony_ci        case IrOpcode::kHeapConstant:
501cb0ef41Sopenharmony_ci        case IrOpcode::kParameter:
511cb0ef41Sopenharmony_ci          return false;
521cb0ef41Sopenharmony_ci        default:
531cb0ef41Sopenharmony_ci          break;
541cb0ef41Sopenharmony_ci      }
551cb0ef41Sopenharmony_ci    } else if (a->opcode() == IrOpcode::kAllocate) {
561cb0ef41Sopenharmony_ci      switch (b->opcode()) {
571cb0ef41Sopenharmony_ci        case IrOpcode::kHeapConstant:
581cb0ef41Sopenharmony_ci        case IrOpcode::kParameter:
591cb0ef41Sopenharmony_ci          return false;
601cb0ef41Sopenharmony_ci        default:
611cb0ef41Sopenharmony_ci          break;
621cb0ef41Sopenharmony_ci      }
631cb0ef41Sopenharmony_ci    }
641cb0ef41Sopenharmony_ci  }
651cb0ef41Sopenharmony_ci  return true;
661cb0ef41Sopenharmony_ci}
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_cibool MustAlias(Node* a, Node* b) {
691cb0ef41Sopenharmony_ci  return ResolveRenames(a) == ResolveRenames(b);
701cb0ef41Sopenharmony_ci}
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ci}  // namespace
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ciReduction LoadElimination::Reduce(Node* node) {
751cb0ef41Sopenharmony_ci  if (FLAG_trace_turbo_load_elimination) {
761cb0ef41Sopenharmony_ci    if (node->op()->EffectInputCount() > 0) {
771cb0ef41Sopenharmony_ci      PrintF(" visit #%d:%s", node->id(), node->op()->mnemonic());
781cb0ef41Sopenharmony_ci      if (node->op()->ValueInputCount() > 0) {
791cb0ef41Sopenharmony_ci        PrintF("(");
801cb0ef41Sopenharmony_ci        for (int i = 0; i < node->op()->ValueInputCount(); ++i) {
811cb0ef41Sopenharmony_ci          if (i > 0) PrintF(", ");
821cb0ef41Sopenharmony_ci          Node* const value = NodeProperties::GetValueInput(node, i);
831cb0ef41Sopenharmony_ci          PrintF("#%d:%s", value->id(), value->op()->mnemonic());
841cb0ef41Sopenharmony_ci        }
851cb0ef41Sopenharmony_ci        PrintF(")");
861cb0ef41Sopenharmony_ci      }
871cb0ef41Sopenharmony_ci      PrintF("\n");
881cb0ef41Sopenharmony_ci      for (int i = 0; i < node->op()->EffectInputCount(); ++i) {
891cb0ef41Sopenharmony_ci        Node* const effect = NodeProperties::GetEffectInput(node, i);
901cb0ef41Sopenharmony_ci        if (AbstractState const* const state = node_states_.Get(effect)) {
911cb0ef41Sopenharmony_ci          PrintF("  state[%i]: #%d:%s\n", i, effect->id(),
921cb0ef41Sopenharmony_ci                 effect->op()->mnemonic());
931cb0ef41Sopenharmony_ci          state->Print();
941cb0ef41Sopenharmony_ci        } else {
951cb0ef41Sopenharmony_ci          PrintF("  no state[%i]: #%d:%s\n", i, effect->id(),
961cb0ef41Sopenharmony_ci                 effect->op()->mnemonic());
971cb0ef41Sopenharmony_ci        }
981cb0ef41Sopenharmony_ci      }
991cb0ef41Sopenharmony_ci    }
1001cb0ef41Sopenharmony_ci  }
1011cb0ef41Sopenharmony_ci  switch (node->opcode()) {
1021cb0ef41Sopenharmony_ci    case IrOpcode::kMapGuard:
1031cb0ef41Sopenharmony_ci      return ReduceMapGuard(node);
1041cb0ef41Sopenharmony_ci    case IrOpcode::kCheckMaps:
1051cb0ef41Sopenharmony_ci      return ReduceCheckMaps(node);
1061cb0ef41Sopenharmony_ci    case IrOpcode::kCompareMaps:
1071cb0ef41Sopenharmony_ci      return ReduceCompareMaps(node);
1081cb0ef41Sopenharmony_ci    case IrOpcode::kEnsureWritableFastElements:
1091cb0ef41Sopenharmony_ci      return ReduceEnsureWritableFastElements(node);
1101cb0ef41Sopenharmony_ci    case IrOpcode::kMaybeGrowFastElements:
1111cb0ef41Sopenharmony_ci      return ReduceMaybeGrowFastElements(node);
1121cb0ef41Sopenharmony_ci    case IrOpcode::kTransitionElementsKind:
1131cb0ef41Sopenharmony_ci      return ReduceTransitionElementsKind(node);
1141cb0ef41Sopenharmony_ci    case IrOpcode::kLoadField:
1151cb0ef41Sopenharmony_ci      return ReduceLoadField(node, FieldAccessOf(node->op()));
1161cb0ef41Sopenharmony_ci    case IrOpcode::kStoreField:
1171cb0ef41Sopenharmony_ci      return ReduceStoreField(node, FieldAccessOf(node->op()));
1181cb0ef41Sopenharmony_ci    case IrOpcode::kLoadElement:
1191cb0ef41Sopenharmony_ci      return ReduceLoadElement(node);
1201cb0ef41Sopenharmony_ci    case IrOpcode::kStoreElement:
1211cb0ef41Sopenharmony_ci      return ReduceStoreElement(node);
1221cb0ef41Sopenharmony_ci    case IrOpcode::kTransitionAndStoreElement:
1231cb0ef41Sopenharmony_ci      return ReduceTransitionAndStoreElement(node);
1241cb0ef41Sopenharmony_ci    case IrOpcode::kStoreTypedElement:
1251cb0ef41Sopenharmony_ci      return ReduceStoreTypedElement(node);
1261cb0ef41Sopenharmony_ci    case IrOpcode::kEffectPhi:
1271cb0ef41Sopenharmony_ci      return ReduceEffectPhi(node);
1281cb0ef41Sopenharmony_ci    case IrOpcode::kDead:
1291cb0ef41Sopenharmony_ci      break;
1301cb0ef41Sopenharmony_ci    case IrOpcode::kStart:
1311cb0ef41Sopenharmony_ci      return ReduceStart(node);
1321cb0ef41Sopenharmony_ci    default:
1331cb0ef41Sopenharmony_ci      return ReduceOtherNode(node);
1341cb0ef41Sopenharmony_ci  }
1351cb0ef41Sopenharmony_ci  return NoChange();
1361cb0ef41Sopenharmony_ci}
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_cinamespace {
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_cibool IsCompatible(MachineRepresentation r1, MachineRepresentation r2) {
1411cb0ef41Sopenharmony_ci  if (r1 == r2) return true;
1421cb0ef41Sopenharmony_ci  return IsAnyTagged(r1) && IsAnyTagged(r2);
1431cb0ef41Sopenharmony_ci}
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ci}  // namespace
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_ciLoadElimination::AbstractState const
1481cb0ef41Sopenharmony_ci    LoadElimination::AbstractState::empty_state_;
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ciNode* LoadElimination::AbstractElements::Lookup(
1511cb0ef41Sopenharmony_ci    Node* object, Node* index, MachineRepresentation representation) const {
1521cb0ef41Sopenharmony_ci  for (Element const element : elements_) {
1531cb0ef41Sopenharmony_ci    if (element.object == nullptr) continue;
1541cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(element.index);
1551cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(element.value);
1561cb0ef41Sopenharmony_ci    if (MustAlias(object, element.object) && MustAlias(index, element.index) &&
1571cb0ef41Sopenharmony_ci        IsCompatible(representation, element.representation)) {
1581cb0ef41Sopenharmony_ci      return element.value;
1591cb0ef41Sopenharmony_ci    }
1601cb0ef41Sopenharmony_ci  }
1611cb0ef41Sopenharmony_ci  return nullptr;
1621cb0ef41Sopenharmony_ci}
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ciLoadElimination::AbstractElements const*
1651cb0ef41Sopenharmony_ciLoadElimination::AbstractElements::Kill(Node* object, Node* index,
1661cb0ef41Sopenharmony_ci                                        Zone* zone) const {
1671cb0ef41Sopenharmony_ci  for (Element const element : this->elements_) {
1681cb0ef41Sopenharmony_ci    if (element.object == nullptr) continue;
1691cb0ef41Sopenharmony_ci    if (MayAlias(object, element.object)) {
1701cb0ef41Sopenharmony_ci      AbstractElements* that = zone->New<AbstractElements>(zone);
1711cb0ef41Sopenharmony_ci      for (Element const element2 : this->elements_) {
1721cb0ef41Sopenharmony_ci        if (element2.object == nullptr) continue;
1731cb0ef41Sopenharmony_ci        DCHECK_NOT_NULL(element2.index);
1741cb0ef41Sopenharmony_ci        DCHECK_NOT_NULL(element2.value);
1751cb0ef41Sopenharmony_ci        if (!MayAlias(object, element2.object) ||
1761cb0ef41Sopenharmony_ci            !NodeProperties::GetType(index).Maybe(
1771cb0ef41Sopenharmony_ci                NodeProperties::GetType(element2.index))) {
1781cb0ef41Sopenharmony_ci          that->elements_[that->next_index_++] = element2;
1791cb0ef41Sopenharmony_ci        }
1801cb0ef41Sopenharmony_ci      }
1811cb0ef41Sopenharmony_ci      that->next_index_ %= arraysize(elements_);
1821cb0ef41Sopenharmony_ci      return that;
1831cb0ef41Sopenharmony_ci    }
1841cb0ef41Sopenharmony_ci  }
1851cb0ef41Sopenharmony_ci  return this;
1861cb0ef41Sopenharmony_ci}
1871cb0ef41Sopenharmony_ci
1881cb0ef41Sopenharmony_cibool LoadElimination::AbstractElements::Equals(
1891cb0ef41Sopenharmony_ci    AbstractElements const* that) const {
1901cb0ef41Sopenharmony_ci  if (this == that) return true;
1911cb0ef41Sopenharmony_ci  for (size_t i = 0; i < arraysize(elements_); ++i) {
1921cb0ef41Sopenharmony_ci    Element this_element = this->elements_[i];
1931cb0ef41Sopenharmony_ci    if (this_element.object == nullptr) continue;
1941cb0ef41Sopenharmony_ci    for (size_t j = 0;; ++j) {
1951cb0ef41Sopenharmony_ci      if (j == arraysize(elements_)) return false;
1961cb0ef41Sopenharmony_ci      Element that_element = that->elements_[j];
1971cb0ef41Sopenharmony_ci      if (this_element.object == that_element.object &&
1981cb0ef41Sopenharmony_ci          this_element.index == that_element.index &&
1991cb0ef41Sopenharmony_ci          this_element.value == that_element.value) {
2001cb0ef41Sopenharmony_ci        break;
2011cb0ef41Sopenharmony_ci      }
2021cb0ef41Sopenharmony_ci    }
2031cb0ef41Sopenharmony_ci  }
2041cb0ef41Sopenharmony_ci  for (size_t i = 0; i < arraysize(elements_); ++i) {
2051cb0ef41Sopenharmony_ci    Element that_element = that->elements_[i];
2061cb0ef41Sopenharmony_ci    if (that_element.object == nullptr) continue;
2071cb0ef41Sopenharmony_ci    for (size_t j = 0;; ++j) {
2081cb0ef41Sopenharmony_ci      if (j == arraysize(elements_)) return false;
2091cb0ef41Sopenharmony_ci      Element this_element = this->elements_[j];
2101cb0ef41Sopenharmony_ci      if (that_element.object == this_element.object &&
2111cb0ef41Sopenharmony_ci          that_element.index == this_element.index &&
2121cb0ef41Sopenharmony_ci          that_element.value == this_element.value) {
2131cb0ef41Sopenharmony_ci        break;
2141cb0ef41Sopenharmony_ci      }
2151cb0ef41Sopenharmony_ci    }
2161cb0ef41Sopenharmony_ci  }
2171cb0ef41Sopenharmony_ci  return true;
2181cb0ef41Sopenharmony_ci}
2191cb0ef41Sopenharmony_ci
2201cb0ef41Sopenharmony_ciLoadElimination::AbstractElements const*
2211cb0ef41Sopenharmony_ciLoadElimination::AbstractElements::Merge(AbstractElements const* that,
2221cb0ef41Sopenharmony_ci                                         Zone* zone) const {
2231cb0ef41Sopenharmony_ci  if (this->Equals(that)) return this;
2241cb0ef41Sopenharmony_ci  AbstractElements* copy = zone->New<AbstractElements>(zone);
2251cb0ef41Sopenharmony_ci  for (Element const this_element : this->elements_) {
2261cb0ef41Sopenharmony_ci    if (this_element.object == nullptr) continue;
2271cb0ef41Sopenharmony_ci    for (Element const that_element : that->elements_) {
2281cb0ef41Sopenharmony_ci      if (this_element.object == that_element.object &&
2291cb0ef41Sopenharmony_ci          this_element.index == that_element.index &&
2301cb0ef41Sopenharmony_ci          this_element.value == that_element.value) {
2311cb0ef41Sopenharmony_ci        copy->elements_[copy->next_index_++] = this_element;
2321cb0ef41Sopenharmony_ci        break;
2331cb0ef41Sopenharmony_ci      }
2341cb0ef41Sopenharmony_ci    }
2351cb0ef41Sopenharmony_ci  }
2361cb0ef41Sopenharmony_ci  copy->next_index_ %= arraysize(elements_);
2371cb0ef41Sopenharmony_ci  return copy;
2381cb0ef41Sopenharmony_ci}
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_civoid LoadElimination::AbstractElements::Print() const {
2411cb0ef41Sopenharmony_ci  for (Element const& element : elements_) {
2421cb0ef41Sopenharmony_ci    if (element.object) {
2431cb0ef41Sopenharmony_ci      PrintF("    #%d:%s @ #%d:%s -> #%d:%s\n", element.object->id(),
2441cb0ef41Sopenharmony_ci             element.object->op()->mnemonic(), element.index->id(),
2451cb0ef41Sopenharmony_ci             element.index->op()->mnemonic(), element.value->id(),
2461cb0ef41Sopenharmony_ci             element.value->op()->mnemonic());
2471cb0ef41Sopenharmony_ci    }
2481cb0ef41Sopenharmony_ci  }
2491cb0ef41Sopenharmony_ci}
2501cb0ef41Sopenharmony_ci
2511cb0ef41Sopenharmony_ciLoadElimination::FieldInfo const* LoadElimination::AbstractField::Lookup(
2521cb0ef41Sopenharmony_ci    Node* object) const {
2531cb0ef41Sopenharmony_ci  for (auto& pair : info_for_node_) {
2541cb0ef41Sopenharmony_ci    if (pair.first->IsDead()) continue;
2551cb0ef41Sopenharmony_ci    if (MustAlias(object, pair.first)) return &pair.second;
2561cb0ef41Sopenharmony_ci  }
2571cb0ef41Sopenharmony_ci  return nullptr;
2581cb0ef41Sopenharmony_ci}
2591cb0ef41Sopenharmony_ci
2601cb0ef41Sopenharmony_cinamespace {
2611cb0ef41Sopenharmony_ci
2621cb0ef41Sopenharmony_cibool MayAlias(MaybeHandle<Name> x, MaybeHandle<Name> y) {
2631cb0ef41Sopenharmony_ci  if (!x.address()) return true;
2641cb0ef41Sopenharmony_ci  if (!y.address()) return true;
2651cb0ef41Sopenharmony_ci  if (x.address() != y.address()) return false;
2661cb0ef41Sopenharmony_ci  return true;
2671cb0ef41Sopenharmony_ci}
2681cb0ef41Sopenharmony_ci
2691cb0ef41Sopenharmony_ci}  // namespace
2701cb0ef41Sopenharmony_ci
2711cb0ef41Sopenharmony_ciclass LoadElimination::AliasStateInfo {
2721cb0ef41Sopenharmony_ci public:
2731cb0ef41Sopenharmony_ci  AliasStateInfo(const AbstractState* state, Node* object, Handle<Map> map)
2741cb0ef41Sopenharmony_ci      : state_(state), object_(object), map_(map) {}
2751cb0ef41Sopenharmony_ci  AliasStateInfo(const AbstractState* state, Node* object)
2761cb0ef41Sopenharmony_ci      : state_(state), object_(object) {}
2771cb0ef41Sopenharmony_ci
2781cb0ef41Sopenharmony_ci  bool MayAlias(Node* other) const;
2791cb0ef41Sopenharmony_ci
2801cb0ef41Sopenharmony_ci private:
2811cb0ef41Sopenharmony_ci  const AbstractState* state_;
2821cb0ef41Sopenharmony_ci  Node* object_;
2831cb0ef41Sopenharmony_ci  MaybeHandle<Map> map_;
2841cb0ef41Sopenharmony_ci};
2851cb0ef41Sopenharmony_ci
2861cb0ef41Sopenharmony_ciLoadElimination::AbstractField const* LoadElimination::AbstractField::KillConst(
2871cb0ef41Sopenharmony_ci    Node* object, Zone* zone) const {
2881cb0ef41Sopenharmony_ci  for (auto info1 : this->info_for_node_) {
2891cb0ef41Sopenharmony_ci    if (info1.first->IsDead()) continue;
2901cb0ef41Sopenharmony_ci    // If we previously recorded information about a const store on the given
2911cb0ef41Sopenharmony_ci    // 'object', we might not have done it on the same node; e.g. we might now
2921cb0ef41Sopenharmony_ci    // identify the object by a FinishRegion node, whereas the initial const
2931cb0ef41Sopenharmony_ci    // store was performed on the Allocate node. We therefore remove information
2941cb0ef41Sopenharmony_ci    // on all nodes that must alias with 'object'.
2951cb0ef41Sopenharmony_ci    if (MustAlias(object, info1.first)) {
2961cb0ef41Sopenharmony_ci      AbstractField* that = zone->New<AbstractField>(zone);
2971cb0ef41Sopenharmony_ci      for (auto info2 : this->info_for_node_) {
2981cb0ef41Sopenharmony_ci        if (!MustAlias(object, info2.first)) {
2991cb0ef41Sopenharmony_ci          that->info_for_node_.insert(info2);
3001cb0ef41Sopenharmony_ci        }
3011cb0ef41Sopenharmony_ci      }
3021cb0ef41Sopenharmony_ci      return that;
3031cb0ef41Sopenharmony_ci    }
3041cb0ef41Sopenharmony_ci  }
3051cb0ef41Sopenharmony_ci  return this;
3061cb0ef41Sopenharmony_ci}
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_ciLoadElimination::AbstractField const* LoadElimination::AbstractField::Kill(
3091cb0ef41Sopenharmony_ci    const AliasStateInfo& alias_info, MaybeHandle<Name> name,
3101cb0ef41Sopenharmony_ci    Zone* zone) const {
3111cb0ef41Sopenharmony_ci  for (auto info1 : this->info_for_node_) {
3121cb0ef41Sopenharmony_ci    if (info1.first->IsDead()) continue;
3131cb0ef41Sopenharmony_ci    if (alias_info.MayAlias(info1.first)) {
3141cb0ef41Sopenharmony_ci      AbstractField* that = zone->New<AbstractField>(zone);
3151cb0ef41Sopenharmony_ci      for (auto info2 : this->info_for_node_) {
3161cb0ef41Sopenharmony_ci        if (!alias_info.MayAlias(info2.first) ||
3171cb0ef41Sopenharmony_ci            !MayAlias(name, info2.second.name)) {
3181cb0ef41Sopenharmony_ci          that->info_for_node_.insert(info2);
3191cb0ef41Sopenharmony_ci        }
3201cb0ef41Sopenharmony_ci      }
3211cb0ef41Sopenharmony_ci      return that;
3221cb0ef41Sopenharmony_ci    }
3231cb0ef41Sopenharmony_ci  }
3241cb0ef41Sopenharmony_ci  return this;
3251cb0ef41Sopenharmony_ci}
3261cb0ef41Sopenharmony_ci
3271cb0ef41Sopenharmony_civoid LoadElimination::AbstractField::Print() const {
3281cb0ef41Sopenharmony_ci  for (auto pair : info_for_node_) {
3291cb0ef41Sopenharmony_ci    PrintF("    #%d:%s -> #%d:%s [repr=%s]\n", pair.first->id(),
3301cb0ef41Sopenharmony_ci           pair.first->op()->mnemonic(), pair.second.value->id(),
3311cb0ef41Sopenharmony_ci           pair.second.value->op()->mnemonic(),
3321cb0ef41Sopenharmony_ci           MachineReprToString(pair.second.representation));
3331cb0ef41Sopenharmony_ci  }
3341cb0ef41Sopenharmony_ci}
3351cb0ef41Sopenharmony_ci
3361cb0ef41Sopenharmony_ciLoadElimination::AbstractMaps::AbstractMaps(Zone* zone)
3371cb0ef41Sopenharmony_ci    : info_for_node_(zone) {}
3381cb0ef41Sopenharmony_ci
3391cb0ef41Sopenharmony_ciLoadElimination::AbstractMaps::AbstractMaps(Node* object,
3401cb0ef41Sopenharmony_ci                                            ZoneHandleSet<Map> maps, Zone* zone)
3411cb0ef41Sopenharmony_ci    : info_for_node_(zone) {
3421cb0ef41Sopenharmony_ci  object = ResolveRenames(object);
3431cb0ef41Sopenharmony_ci  info_for_node_.insert(std::make_pair(object, maps));
3441cb0ef41Sopenharmony_ci}
3451cb0ef41Sopenharmony_ci
3461cb0ef41Sopenharmony_cibool LoadElimination::AbstractMaps::Lookup(
3471cb0ef41Sopenharmony_ci    Node* object, ZoneHandleSet<Map>* object_maps) const {
3481cb0ef41Sopenharmony_ci  auto it = info_for_node_.find(ResolveRenames(object));
3491cb0ef41Sopenharmony_ci  if (it == info_for_node_.end()) return false;
3501cb0ef41Sopenharmony_ci  *object_maps = it->second;
3511cb0ef41Sopenharmony_ci  return true;
3521cb0ef41Sopenharmony_ci}
3531cb0ef41Sopenharmony_ci
3541cb0ef41Sopenharmony_ciLoadElimination::AbstractMaps const* LoadElimination::AbstractMaps::Kill(
3551cb0ef41Sopenharmony_ci    const AliasStateInfo& alias_info, Zone* zone) const {
3561cb0ef41Sopenharmony_ci  for (auto info1 : this->info_for_node_) {
3571cb0ef41Sopenharmony_ci    if (alias_info.MayAlias(info1.first)) {
3581cb0ef41Sopenharmony_ci      AbstractMaps* that = zone->New<AbstractMaps>(zone);
3591cb0ef41Sopenharmony_ci      for (auto info2 : this->info_for_node_) {
3601cb0ef41Sopenharmony_ci        if (!alias_info.MayAlias(info2.first))
3611cb0ef41Sopenharmony_ci          that->info_for_node_.insert(info2);
3621cb0ef41Sopenharmony_ci      }
3631cb0ef41Sopenharmony_ci      return that;
3641cb0ef41Sopenharmony_ci    }
3651cb0ef41Sopenharmony_ci  }
3661cb0ef41Sopenharmony_ci  return this;
3671cb0ef41Sopenharmony_ci}
3681cb0ef41Sopenharmony_ci
3691cb0ef41Sopenharmony_ciLoadElimination::AbstractMaps const* LoadElimination::AbstractMaps::Merge(
3701cb0ef41Sopenharmony_ci    AbstractMaps const* that, Zone* zone) const {
3711cb0ef41Sopenharmony_ci  if (this->Equals(that)) return this;
3721cb0ef41Sopenharmony_ci  AbstractMaps* copy = zone->New<AbstractMaps>(zone);
3731cb0ef41Sopenharmony_ci  for (auto this_it : this->info_for_node_) {
3741cb0ef41Sopenharmony_ci    Node* this_object = this_it.first;
3751cb0ef41Sopenharmony_ci    ZoneHandleSet<Map> this_maps = this_it.second;
3761cb0ef41Sopenharmony_ci    auto that_it = that->info_for_node_.find(this_object);
3771cb0ef41Sopenharmony_ci    if (that_it != that->info_for_node_.end() && that_it->second == this_maps) {
3781cb0ef41Sopenharmony_ci      copy->info_for_node_.insert(this_it);
3791cb0ef41Sopenharmony_ci    }
3801cb0ef41Sopenharmony_ci  }
3811cb0ef41Sopenharmony_ci  return copy;
3821cb0ef41Sopenharmony_ci}
3831cb0ef41Sopenharmony_ci
3841cb0ef41Sopenharmony_ciLoadElimination::AbstractMaps const* LoadElimination::AbstractMaps::Extend(
3851cb0ef41Sopenharmony_ci    Node* object, ZoneHandleSet<Map> maps, Zone* zone) const {
3861cb0ef41Sopenharmony_ci  AbstractMaps* that = zone->New<AbstractMaps>(zone);
3871cb0ef41Sopenharmony_ci  that->info_for_node_ = this->info_for_node_;
3881cb0ef41Sopenharmony_ci  object = ResolveRenames(object);
3891cb0ef41Sopenharmony_ci  that->info_for_node_[object] = maps;
3901cb0ef41Sopenharmony_ci  return that;
3911cb0ef41Sopenharmony_ci}
3921cb0ef41Sopenharmony_ci
3931cb0ef41Sopenharmony_civoid LoadElimination::AbstractMaps::Print() const {
3941cb0ef41Sopenharmony_ci  AllowHandleDereference allow_handle_dereference;
3951cb0ef41Sopenharmony_ci  StdoutStream os;
3961cb0ef41Sopenharmony_ci  for (auto pair : info_for_node_) {
3971cb0ef41Sopenharmony_ci    os << "    #" << pair.first->id() << ":" << pair.first->op()->mnemonic()
3981cb0ef41Sopenharmony_ci       << std::endl;
3991cb0ef41Sopenharmony_ci    ZoneHandleSet<Map> const& maps = pair.second;
4001cb0ef41Sopenharmony_ci    for (size_t i = 0; i < maps.size(); ++i) {
4011cb0ef41Sopenharmony_ci      os << "     - " << Brief(*maps[i]) << std::endl;
4021cb0ef41Sopenharmony_ci    }
4031cb0ef41Sopenharmony_ci  }
4041cb0ef41Sopenharmony_ci}
4051cb0ef41Sopenharmony_ci
4061cb0ef41Sopenharmony_cibool LoadElimination::AbstractState::FieldsEquals(
4071cb0ef41Sopenharmony_ci    AbstractFields const& this_fields,
4081cb0ef41Sopenharmony_ci    AbstractFields const& that_fields) const {
4091cb0ef41Sopenharmony_ci  for (size_t i = 0u; i < this_fields.size(); ++i) {
4101cb0ef41Sopenharmony_ci    AbstractField const* this_field = this_fields[i];
4111cb0ef41Sopenharmony_ci    AbstractField const* that_field = that_fields[i];
4121cb0ef41Sopenharmony_ci    if (this_field) {
4131cb0ef41Sopenharmony_ci      if (!that_field || !that_field->Equals(this_field)) return false;
4141cb0ef41Sopenharmony_ci    } else if (that_field) {
4151cb0ef41Sopenharmony_ci      return false;
4161cb0ef41Sopenharmony_ci    }
4171cb0ef41Sopenharmony_ci  }
4181cb0ef41Sopenharmony_ci  return true;
4191cb0ef41Sopenharmony_ci}
4201cb0ef41Sopenharmony_ci
4211cb0ef41Sopenharmony_cibool LoadElimination::AbstractState::Equals(AbstractState const* that) const {
4221cb0ef41Sopenharmony_ci  if (this->elements_) {
4231cb0ef41Sopenharmony_ci    if (!that->elements_ || !that->elements_->Equals(this->elements_)) {
4241cb0ef41Sopenharmony_ci      return false;
4251cb0ef41Sopenharmony_ci    }
4261cb0ef41Sopenharmony_ci  } else if (that->elements_) {
4271cb0ef41Sopenharmony_ci    return false;
4281cb0ef41Sopenharmony_ci  }
4291cb0ef41Sopenharmony_ci  if (!FieldsEquals(this->fields_, that->fields_) ||
4301cb0ef41Sopenharmony_ci      !FieldsEquals(this->const_fields_, that->const_fields_)) {
4311cb0ef41Sopenharmony_ci    return false;
4321cb0ef41Sopenharmony_ci  }
4331cb0ef41Sopenharmony_ci  if (this->maps_) {
4341cb0ef41Sopenharmony_ci    if (!that->maps_ || !that->maps_->Equals(this->maps_)) {
4351cb0ef41Sopenharmony_ci      return false;
4361cb0ef41Sopenharmony_ci    }
4371cb0ef41Sopenharmony_ci  } else if (that->maps_) {
4381cb0ef41Sopenharmony_ci    return false;
4391cb0ef41Sopenharmony_ci  }
4401cb0ef41Sopenharmony_ci  return true;
4411cb0ef41Sopenharmony_ci}
4421cb0ef41Sopenharmony_ci
4431cb0ef41Sopenharmony_civoid LoadElimination::AbstractState::FieldsMerge(
4441cb0ef41Sopenharmony_ci    AbstractFields* this_fields, AbstractFields const& that_fields,
4451cb0ef41Sopenharmony_ci    Zone* zone) {
4461cb0ef41Sopenharmony_ci  for (size_t i = 0; i < this_fields->size(); ++i) {
4471cb0ef41Sopenharmony_ci    AbstractField const*& this_field = (*this_fields)[i];
4481cb0ef41Sopenharmony_ci    if (this_field) {
4491cb0ef41Sopenharmony_ci      if (that_fields[i]) {
4501cb0ef41Sopenharmony_ci        this_field = this_field->Merge(that_fields[i], zone);
4511cb0ef41Sopenharmony_ci      } else {
4521cb0ef41Sopenharmony_ci        this_field = nullptr;
4531cb0ef41Sopenharmony_ci      }
4541cb0ef41Sopenharmony_ci    }
4551cb0ef41Sopenharmony_ci  }
4561cb0ef41Sopenharmony_ci}
4571cb0ef41Sopenharmony_ci
4581cb0ef41Sopenharmony_civoid LoadElimination::AbstractState::Merge(AbstractState const* that,
4591cb0ef41Sopenharmony_ci                                           Zone* zone) {
4601cb0ef41Sopenharmony_ci  // Merge the information we have about the elements.
4611cb0ef41Sopenharmony_ci  if (this->elements_) {
4621cb0ef41Sopenharmony_ci    this->elements_ = that->elements_
4631cb0ef41Sopenharmony_ci                          ? that->elements_->Merge(this->elements_, zone)
4641cb0ef41Sopenharmony_ci                          : nullptr;
4651cb0ef41Sopenharmony_ci  }
4661cb0ef41Sopenharmony_ci
4671cb0ef41Sopenharmony_ci  // Merge the information we have about the fields.
4681cb0ef41Sopenharmony_ci  FieldsMerge(&this->fields_, that->fields_, zone);
4691cb0ef41Sopenharmony_ci  FieldsMerge(&this->const_fields_, that->const_fields_, zone);
4701cb0ef41Sopenharmony_ci
4711cb0ef41Sopenharmony_ci  // Merge the information we have about the maps.
4721cb0ef41Sopenharmony_ci  if (this->maps_) {
4731cb0ef41Sopenharmony_ci    this->maps_ = that->maps_ ? that->maps_->Merge(this->maps_, zone) : nullptr;
4741cb0ef41Sopenharmony_ci  }
4751cb0ef41Sopenharmony_ci}
4761cb0ef41Sopenharmony_ci
4771cb0ef41Sopenharmony_cibool LoadElimination::AbstractState::LookupMaps(
4781cb0ef41Sopenharmony_ci    Node* object, ZoneHandleSet<Map>* object_map) const {
4791cb0ef41Sopenharmony_ci  return this->maps_ && this->maps_->Lookup(object, object_map);
4801cb0ef41Sopenharmony_ci}
4811cb0ef41Sopenharmony_ci
4821cb0ef41Sopenharmony_ciLoadElimination::AbstractState const* LoadElimination::AbstractState::SetMaps(
4831cb0ef41Sopenharmony_ci    Node* object, ZoneHandleSet<Map> maps, Zone* zone) const {
4841cb0ef41Sopenharmony_ci  AbstractState* that = zone->New<AbstractState>(*this);
4851cb0ef41Sopenharmony_ci  if (that->maps_) {
4861cb0ef41Sopenharmony_ci    that->maps_ = that->maps_->Extend(object, maps, zone);
4871cb0ef41Sopenharmony_ci  } else {
4881cb0ef41Sopenharmony_ci    that->maps_ = zone->New<AbstractMaps>(object, maps, zone);
4891cb0ef41Sopenharmony_ci  }
4901cb0ef41Sopenharmony_ci  return that;
4911cb0ef41Sopenharmony_ci}
4921cb0ef41Sopenharmony_ci
4931cb0ef41Sopenharmony_ciLoadElimination::AbstractState const* LoadElimination::AbstractState::KillMaps(
4941cb0ef41Sopenharmony_ci    const AliasStateInfo& alias_info, Zone* zone) const {
4951cb0ef41Sopenharmony_ci  if (this->maps_) {
4961cb0ef41Sopenharmony_ci    AbstractMaps const* that_maps = this->maps_->Kill(alias_info, zone);
4971cb0ef41Sopenharmony_ci    if (this->maps_ != that_maps) {
4981cb0ef41Sopenharmony_ci      AbstractState* that = zone->New<AbstractState>(*this);
4991cb0ef41Sopenharmony_ci      that->maps_ = that_maps;
5001cb0ef41Sopenharmony_ci      return that;
5011cb0ef41Sopenharmony_ci    }
5021cb0ef41Sopenharmony_ci  }
5031cb0ef41Sopenharmony_ci  return this;
5041cb0ef41Sopenharmony_ci}
5051cb0ef41Sopenharmony_ci
5061cb0ef41Sopenharmony_ciLoadElimination::AbstractState const* LoadElimination::AbstractState::KillMaps(
5071cb0ef41Sopenharmony_ci    Node* object, Zone* zone) const {
5081cb0ef41Sopenharmony_ci  AliasStateInfo alias_info(this, object);
5091cb0ef41Sopenharmony_ci  return KillMaps(alias_info, zone);
5101cb0ef41Sopenharmony_ci}
5111cb0ef41Sopenharmony_ci
5121cb0ef41Sopenharmony_ciNode* LoadElimination::AbstractState::LookupElement(
5131cb0ef41Sopenharmony_ci    Node* object, Node* index, MachineRepresentation representation) const {
5141cb0ef41Sopenharmony_ci  if (this->elements_) {
5151cb0ef41Sopenharmony_ci    return this->elements_->Lookup(object, index, representation);
5161cb0ef41Sopenharmony_ci  }
5171cb0ef41Sopenharmony_ci  return nullptr;
5181cb0ef41Sopenharmony_ci}
5191cb0ef41Sopenharmony_ci
5201cb0ef41Sopenharmony_ciLoadElimination::AbstractState const*
5211cb0ef41Sopenharmony_ciLoadElimination::AbstractState::AddElement(Node* object, Node* index,
5221cb0ef41Sopenharmony_ci                                           Node* value,
5231cb0ef41Sopenharmony_ci                                           MachineRepresentation representation,
5241cb0ef41Sopenharmony_ci                                           Zone* zone) const {
5251cb0ef41Sopenharmony_ci  AbstractState* that = zone->New<AbstractState>(*this);
5261cb0ef41Sopenharmony_ci  if (that->elements_) {
5271cb0ef41Sopenharmony_ci    that->elements_ =
5281cb0ef41Sopenharmony_ci        that->elements_->Extend(object, index, value, representation, zone);
5291cb0ef41Sopenharmony_ci  } else {
5301cb0ef41Sopenharmony_ci    that->elements_ =
5311cb0ef41Sopenharmony_ci        zone->New<AbstractElements>(object, index, value, representation, zone);
5321cb0ef41Sopenharmony_ci  }
5331cb0ef41Sopenharmony_ci  return that;
5341cb0ef41Sopenharmony_ci}
5351cb0ef41Sopenharmony_ci
5361cb0ef41Sopenharmony_ciLoadElimination::AbstractState const*
5371cb0ef41Sopenharmony_ciLoadElimination::AbstractState::KillElement(Node* object, Node* index,
5381cb0ef41Sopenharmony_ci                                            Zone* zone) const {
5391cb0ef41Sopenharmony_ci  if (this->elements_) {
5401cb0ef41Sopenharmony_ci    AbstractElements const* that_elements =
5411cb0ef41Sopenharmony_ci        this->elements_->Kill(object, index, zone);
5421cb0ef41Sopenharmony_ci    if (this->elements_ != that_elements) {
5431cb0ef41Sopenharmony_ci      AbstractState* that = zone->New<AbstractState>(*this);
5441cb0ef41Sopenharmony_ci      that->elements_ = that_elements;
5451cb0ef41Sopenharmony_ci      return that;
5461cb0ef41Sopenharmony_ci    }
5471cb0ef41Sopenharmony_ci  }
5481cb0ef41Sopenharmony_ci  return this;
5491cb0ef41Sopenharmony_ci}
5501cb0ef41Sopenharmony_ci
5511cb0ef41Sopenharmony_ciLoadElimination::AbstractState const* LoadElimination::AbstractState::AddField(
5521cb0ef41Sopenharmony_ci    Node* object, IndexRange index_range, LoadElimination::FieldInfo info,
5531cb0ef41Sopenharmony_ci    Zone* zone) const {
5541cb0ef41Sopenharmony_ci  AbstractState* that = zone->New<AbstractState>(*this);
5551cb0ef41Sopenharmony_ci  AbstractFields& fields =
5561cb0ef41Sopenharmony_ci      info.const_field_info.IsConst() ? that->const_fields_ : that->fields_;
5571cb0ef41Sopenharmony_ci  for (int index : index_range) {
5581cb0ef41Sopenharmony_ci    if (fields[index]) {
5591cb0ef41Sopenharmony_ci      fields[index] = fields[index]->Extend(object, info, zone);
5601cb0ef41Sopenharmony_ci    } else {
5611cb0ef41Sopenharmony_ci      fields[index] = zone->New<AbstractField>(object, info, zone);
5621cb0ef41Sopenharmony_ci    }
5631cb0ef41Sopenharmony_ci  }
5641cb0ef41Sopenharmony_ci  return that;
5651cb0ef41Sopenharmony_ci}
5661cb0ef41Sopenharmony_ci
5671cb0ef41Sopenharmony_ciLoadElimination::AbstractState const*
5681cb0ef41Sopenharmony_ciLoadElimination::AbstractState::KillConstField(Node* object,
5691cb0ef41Sopenharmony_ci                                               IndexRange index_range,
5701cb0ef41Sopenharmony_ci                                               Zone* zone) const {
5711cb0ef41Sopenharmony_ci  AliasStateInfo alias_info(this, object);
5721cb0ef41Sopenharmony_ci  AbstractState* that = nullptr;
5731cb0ef41Sopenharmony_ci  for (int index : index_range) {
5741cb0ef41Sopenharmony_ci    if (AbstractField const* this_field = this->const_fields_[index]) {
5751cb0ef41Sopenharmony_ci      this_field = this_field->KillConst(object, zone);
5761cb0ef41Sopenharmony_ci      if (this->const_fields_[index] != this_field) {
5771cb0ef41Sopenharmony_ci        if (!that) that = zone->New<AbstractState>(*this);
5781cb0ef41Sopenharmony_ci        that->const_fields_[index] = this_field;
5791cb0ef41Sopenharmony_ci      }
5801cb0ef41Sopenharmony_ci    }
5811cb0ef41Sopenharmony_ci  }
5821cb0ef41Sopenharmony_ci  return that ? that : this;
5831cb0ef41Sopenharmony_ci}
5841cb0ef41Sopenharmony_ci
5851cb0ef41Sopenharmony_ciLoadElimination::AbstractState const* LoadElimination::AbstractState::KillField(
5861cb0ef41Sopenharmony_ci    Node* object, IndexRange index_range, MaybeHandle<Name> name,
5871cb0ef41Sopenharmony_ci    Zone* zone) const {
5881cb0ef41Sopenharmony_ci  AliasStateInfo alias_info(this, object);
5891cb0ef41Sopenharmony_ci  return KillField(alias_info, index_range, name, zone);
5901cb0ef41Sopenharmony_ci}
5911cb0ef41Sopenharmony_ci
5921cb0ef41Sopenharmony_ciLoadElimination::AbstractState const* LoadElimination::AbstractState::KillField(
5931cb0ef41Sopenharmony_ci    const AliasStateInfo& alias_info, IndexRange index_range,
5941cb0ef41Sopenharmony_ci    MaybeHandle<Name> name, Zone* zone) const {
5951cb0ef41Sopenharmony_ci  AbstractState* that = nullptr;
5961cb0ef41Sopenharmony_ci  for (int index : index_range) {
5971cb0ef41Sopenharmony_ci    if (AbstractField const* this_field = this->fields_[index]) {
5981cb0ef41Sopenharmony_ci      this_field = this_field->Kill(alias_info, name, zone);
5991cb0ef41Sopenharmony_ci      if (this->fields_[index] != this_field) {
6001cb0ef41Sopenharmony_ci        if (!that) that = zone->New<AbstractState>(*this);
6011cb0ef41Sopenharmony_ci        that->fields_[index] = this_field;
6021cb0ef41Sopenharmony_ci      }
6031cb0ef41Sopenharmony_ci    }
6041cb0ef41Sopenharmony_ci  }
6051cb0ef41Sopenharmony_ci  return that ? that : this;
6061cb0ef41Sopenharmony_ci}
6071cb0ef41Sopenharmony_ci
6081cb0ef41Sopenharmony_ciLoadElimination::AbstractState const*
6091cb0ef41Sopenharmony_ciLoadElimination::AbstractState::KillFields(Node* object, MaybeHandle<Name> name,
6101cb0ef41Sopenharmony_ci                                           Zone* zone) const {
6111cb0ef41Sopenharmony_ci  AliasStateInfo alias_info(this, object);
6121cb0ef41Sopenharmony_ci  for (size_t i = 0;; ++i) {
6131cb0ef41Sopenharmony_ci    if (i == fields_.size()) return this;
6141cb0ef41Sopenharmony_ci    if (AbstractField const* this_field = this->fields_[i]) {
6151cb0ef41Sopenharmony_ci      AbstractField const* that_field =
6161cb0ef41Sopenharmony_ci          this_field->Kill(alias_info, name, zone);
6171cb0ef41Sopenharmony_ci      if (that_field != this_field) {
6181cb0ef41Sopenharmony_ci        AbstractState* that = zone->New<AbstractState>(*this);
6191cb0ef41Sopenharmony_ci        that->fields_[i] = that_field;
6201cb0ef41Sopenharmony_ci        while (++i < fields_.size()) {
6211cb0ef41Sopenharmony_ci          if (this->fields_[i] != nullptr) {
6221cb0ef41Sopenharmony_ci            that->fields_[i] = this->fields_[i]->Kill(alias_info, name, zone);
6231cb0ef41Sopenharmony_ci          }
6241cb0ef41Sopenharmony_ci        }
6251cb0ef41Sopenharmony_ci        return that;
6261cb0ef41Sopenharmony_ci      }
6271cb0ef41Sopenharmony_ci    }
6281cb0ef41Sopenharmony_ci  }
6291cb0ef41Sopenharmony_ci}
6301cb0ef41Sopenharmony_ci
6311cb0ef41Sopenharmony_ciLoadElimination::AbstractState const* LoadElimination::AbstractState::KillAll(
6321cb0ef41Sopenharmony_ci    Zone* zone) const {
6331cb0ef41Sopenharmony_ci  // Kill everything except for const fields
6341cb0ef41Sopenharmony_ci  for (size_t i = 0; i < const_fields_.size(); ++i) {
6351cb0ef41Sopenharmony_ci    if (const_fields_[i]) {
6361cb0ef41Sopenharmony_ci      AbstractState* that = zone->New<AbstractState>();
6371cb0ef41Sopenharmony_ci      that->const_fields_ = const_fields_;
6381cb0ef41Sopenharmony_ci      return that;
6391cb0ef41Sopenharmony_ci    }
6401cb0ef41Sopenharmony_ci  }
6411cb0ef41Sopenharmony_ci  return LoadElimination::empty_state();
6421cb0ef41Sopenharmony_ci}
6431cb0ef41Sopenharmony_ci
6441cb0ef41Sopenharmony_ciLoadElimination::FieldInfo const* LoadElimination::AbstractState::LookupField(
6451cb0ef41Sopenharmony_ci    Node* object, IndexRange index_range,
6461cb0ef41Sopenharmony_ci    ConstFieldInfo const_field_info) const {
6471cb0ef41Sopenharmony_ci  // Check if all the indices in {index_range} contain identical information.
6481cb0ef41Sopenharmony_ci  // If not, a partially overlapping access has invalidated part of the value.
6491cb0ef41Sopenharmony_ci  base::Optional<LoadElimination::FieldInfo const*> result;
6501cb0ef41Sopenharmony_ci  for (int index : index_range) {
6511cb0ef41Sopenharmony_ci    LoadElimination::FieldInfo const* info = nullptr;
6521cb0ef41Sopenharmony_ci    if (const_field_info.IsConst()) {
6531cb0ef41Sopenharmony_ci      if (AbstractField const* this_field = const_fields_[index]) {
6541cb0ef41Sopenharmony_ci        info = this_field->Lookup(object);
6551cb0ef41Sopenharmony_ci      }
6561cb0ef41Sopenharmony_ci      if (!(info && info->const_field_info == const_field_info)) return nullptr;
6571cb0ef41Sopenharmony_ci    } else {
6581cb0ef41Sopenharmony_ci      if (AbstractField const* this_field = fields_[index]) {
6591cb0ef41Sopenharmony_ci        info = this_field->Lookup(object);
6601cb0ef41Sopenharmony_ci      }
6611cb0ef41Sopenharmony_ci      if (!info) return nullptr;
6621cb0ef41Sopenharmony_ci    }
6631cb0ef41Sopenharmony_ci    if (!result.has_value()) {
6641cb0ef41Sopenharmony_ci      result = info;
6651cb0ef41Sopenharmony_ci    } else if (**result != *info) {
6661cb0ef41Sopenharmony_ci      // We detected inconsistent information for a field here.
6671cb0ef41Sopenharmony_ci      // This can happen when incomplete alias information makes an unrelated
6681cb0ef41Sopenharmony_ci      // write invalidate part of a field and then we re-combine this partial
6691cb0ef41Sopenharmony_ci      // information.
6701cb0ef41Sopenharmony_ci      // This is probably OK, but since it's rare, we better bail out here.
6711cb0ef41Sopenharmony_ci      return nullptr;
6721cb0ef41Sopenharmony_ci    }
6731cb0ef41Sopenharmony_ci  }
6741cb0ef41Sopenharmony_ci  return *result;
6751cb0ef41Sopenharmony_ci}
6761cb0ef41Sopenharmony_ci
6771cb0ef41Sopenharmony_cibool LoadElimination::AliasStateInfo::MayAlias(Node* other) const {
6781cb0ef41Sopenharmony_ci  // If {object} is being initialized right here (indicated by {object} being
6791cb0ef41Sopenharmony_ci  // an Allocate node instead of a FinishRegion node), we know that {other}
6801cb0ef41Sopenharmony_ci  // can only alias with {object} if they refer to exactly the same node.
6811cb0ef41Sopenharmony_ci  if (object_->opcode() == IrOpcode::kAllocate) {
6821cb0ef41Sopenharmony_ci    return object_ == other;
6831cb0ef41Sopenharmony_ci  }
6841cb0ef41Sopenharmony_ci  // Decide aliasing based on the node kinds.
6851cb0ef41Sopenharmony_ci  if (!compiler::MayAlias(object_, other)) {
6861cb0ef41Sopenharmony_ci    return false;
6871cb0ef41Sopenharmony_ci  }
6881cb0ef41Sopenharmony_ci  // Decide aliasing based on maps (if available).
6891cb0ef41Sopenharmony_ci  Handle<Map> map;
6901cb0ef41Sopenharmony_ci  if (map_.ToHandle(&map)) {
6911cb0ef41Sopenharmony_ci    ZoneHandleSet<Map> other_maps;
6921cb0ef41Sopenharmony_ci    if (state_->LookupMaps(other, &other_maps) && other_maps.size() == 1) {
6931cb0ef41Sopenharmony_ci      if (map.address() != other_maps.at(0).address()) {
6941cb0ef41Sopenharmony_ci        return false;
6951cb0ef41Sopenharmony_ci      }
6961cb0ef41Sopenharmony_ci    }
6971cb0ef41Sopenharmony_ci  }
6981cb0ef41Sopenharmony_ci  return true;
6991cb0ef41Sopenharmony_ci}
7001cb0ef41Sopenharmony_ci
7011cb0ef41Sopenharmony_civoid LoadElimination::AbstractState::Print() const {
7021cb0ef41Sopenharmony_ci  if (maps_) {
7031cb0ef41Sopenharmony_ci    PrintF("   maps:\n");
7041cb0ef41Sopenharmony_ci    maps_->Print();
7051cb0ef41Sopenharmony_ci  }
7061cb0ef41Sopenharmony_ci  if (elements_) {
7071cb0ef41Sopenharmony_ci    PrintF("   elements:\n");
7081cb0ef41Sopenharmony_ci    elements_->Print();
7091cb0ef41Sopenharmony_ci  }
7101cb0ef41Sopenharmony_ci  for (size_t i = 0; i < fields_.size(); ++i) {
7111cb0ef41Sopenharmony_ci    if (AbstractField const* const field = fields_[i]) {
7121cb0ef41Sopenharmony_ci      PrintF("   field %zu:\n", i);
7131cb0ef41Sopenharmony_ci      field->Print();
7141cb0ef41Sopenharmony_ci    }
7151cb0ef41Sopenharmony_ci  }
7161cb0ef41Sopenharmony_ci  for (size_t i = 0; i < const_fields_.size(); ++i) {
7171cb0ef41Sopenharmony_ci    if (AbstractField const* const const_field = const_fields_[i]) {
7181cb0ef41Sopenharmony_ci      PrintF("   const field %zu:\n", i);
7191cb0ef41Sopenharmony_ci      const_field->Print();
7201cb0ef41Sopenharmony_ci    }
7211cb0ef41Sopenharmony_ci  }
7221cb0ef41Sopenharmony_ci}
7231cb0ef41Sopenharmony_ci
7241cb0ef41Sopenharmony_ciLoadElimination::AbstractState const*
7251cb0ef41Sopenharmony_ciLoadElimination::AbstractStateForEffectNodes::Get(Node* node) const {
7261cb0ef41Sopenharmony_ci  size_t const id = node->id();
7271cb0ef41Sopenharmony_ci  if (id < info_for_node_.size()) return info_for_node_[id];
7281cb0ef41Sopenharmony_ci  return nullptr;
7291cb0ef41Sopenharmony_ci}
7301cb0ef41Sopenharmony_ci
7311cb0ef41Sopenharmony_civoid LoadElimination::AbstractStateForEffectNodes::Set(
7321cb0ef41Sopenharmony_ci    Node* node, AbstractState const* state) {
7331cb0ef41Sopenharmony_ci  size_t const id = node->id();
7341cb0ef41Sopenharmony_ci  if (id >= info_for_node_.size()) info_for_node_.resize(id + 1, nullptr);
7351cb0ef41Sopenharmony_ci  info_for_node_[id] = state;
7361cb0ef41Sopenharmony_ci}
7371cb0ef41Sopenharmony_ci
7381cb0ef41Sopenharmony_ciReduction LoadElimination::ReduceMapGuard(Node* node) {
7391cb0ef41Sopenharmony_ci  ZoneHandleSet<Map> const& maps = MapGuardMapsOf(node->op());
7401cb0ef41Sopenharmony_ci  Node* const object = NodeProperties::GetValueInput(node, 0);
7411cb0ef41Sopenharmony_ci  Node* const effect = NodeProperties::GetEffectInput(node);
7421cb0ef41Sopenharmony_ci  AbstractState const* state = node_states_.Get(effect);
7431cb0ef41Sopenharmony_ci  if (state == nullptr) return NoChange();
7441cb0ef41Sopenharmony_ci  ZoneHandleSet<Map> object_maps;
7451cb0ef41Sopenharmony_ci  if (state->LookupMaps(object, &object_maps)) {
7461cb0ef41Sopenharmony_ci    if (maps.contains(object_maps)) return Replace(effect);
7471cb0ef41Sopenharmony_ci    // TODO(turbofan): Compute the intersection.
7481cb0ef41Sopenharmony_ci  }
7491cb0ef41Sopenharmony_ci  state = state->SetMaps(object, maps, zone());
7501cb0ef41Sopenharmony_ci  return UpdateState(node, state);
7511cb0ef41Sopenharmony_ci}
7521cb0ef41Sopenharmony_ci
7531cb0ef41Sopenharmony_ciReduction LoadElimination::ReduceCheckMaps(Node* node) {
7541cb0ef41Sopenharmony_ci  ZoneHandleSet<Map> const& maps = CheckMapsParametersOf(node->op()).maps();
7551cb0ef41Sopenharmony_ci  Node* const object = NodeProperties::GetValueInput(node, 0);
7561cb0ef41Sopenharmony_ci  Node* const effect = NodeProperties::GetEffectInput(node);
7571cb0ef41Sopenharmony_ci  AbstractState const* state = node_states_.Get(effect);
7581cb0ef41Sopenharmony_ci  if (state == nullptr) return NoChange();
7591cb0ef41Sopenharmony_ci  ZoneHandleSet<Map> object_maps;
7601cb0ef41Sopenharmony_ci  if (state->LookupMaps(object, &object_maps)) {
7611cb0ef41Sopenharmony_ci    if (maps.contains(object_maps)) return Replace(effect);
7621cb0ef41Sopenharmony_ci    // TODO(turbofan): Compute the intersection.
7631cb0ef41Sopenharmony_ci  }
7641cb0ef41Sopenharmony_ci  state = state->SetMaps(object, maps, zone());
7651cb0ef41Sopenharmony_ci  return UpdateState(node, state);
7661cb0ef41Sopenharmony_ci}
7671cb0ef41Sopenharmony_ci
7681cb0ef41Sopenharmony_ciReduction LoadElimination::ReduceCompareMaps(Node* node) {
7691cb0ef41Sopenharmony_ci  ZoneHandleSet<Map> const& maps = CompareMapsParametersOf(node->op());
7701cb0ef41Sopenharmony_ci  Node* const object = NodeProperties::GetValueInput(node, 0);
7711cb0ef41Sopenharmony_ci  Node* const effect = NodeProperties::GetEffectInput(node);
7721cb0ef41Sopenharmony_ci  AbstractState const* state = node_states_.Get(effect);
7731cb0ef41Sopenharmony_ci  if (state == nullptr) return NoChange();
7741cb0ef41Sopenharmony_ci  ZoneHandleSet<Map> object_maps;
7751cb0ef41Sopenharmony_ci  if (state->LookupMaps(object, &object_maps)) {
7761cb0ef41Sopenharmony_ci    if (maps.contains(object_maps)) {
7771cb0ef41Sopenharmony_ci      Node* value = jsgraph()->TrueConstant();
7781cb0ef41Sopenharmony_ci      ReplaceWithValue(node, value, effect);
7791cb0ef41Sopenharmony_ci      return Replace(value);
7801cb0ef41Sopenharmony_ci    }
7811cb0ef41Sopenharmony_ci    // TODO(turbofan): Compute the intersection.
7821cb0ef41Sopenharmony_ci  }
7831cb0ef41Sopenharmony_ci  return UpdateState(node, state);
7841cb0ef41Sopenharmony_ci}
7851cb0ef41Sopenharmony_ci
7861cb0ef41Sopenharmony_ciReduction LoadElimination::ReduceEnsureWritableFastElements(Node* node) {
7871cb0ef41Sopenharmony_ci  Node* const object = NodeProperties::GetValueInput(node, 0);
7881cb0ef41Sopenharmony_ci  Node* const elements = NodeProperties::GetValueInput(node, 1);
7891cb0ef41Sopenharmony_ci  Node* const effect = NodeProperties::GetEffectInput(node);
7901cb0ef41Sopenharmony_ci  AbstractState const* state = node_states_.Get(effect);
7911cb0ef41Sopenharmony_ci  if (state == nullptr) return NoChange();
7921cb0ef41Sopenharmony_ci  // Check if the {elements} already have the fixed array map.
7931cb0ef41Sopenharmony_ci  ZoneHandleSet<Map> elements_maps;
7941cb0ef41Sopenharmony_ci  ZoneHandleSet<Map> fixed_array_maps(factory()->fixed_array_map());
7951cb0ef41Sopenharmony_ci  if (state->LookupMaps(elements, &elements_maps) &&
7961cb0ef41Sopenharmony_ci      fixed_array_maps.contains(elements_maps)) {
7971cb0ef41Sopenharmony_ci    ReplaceWithValue(node, elements, effect);
7981cb0ef41Sopenharmony_ci    return Replace(elements);
7991cb0ef41Sopenharmony_ci  }
8001cb0ef41Sopenharmony_ci  // We know that the resulting elements have the fixed array map.
8011cb0ef41Sopenharmony_ci  state = state->SetMaps(node, fixed_array_maps, zone());
8021cb0ef41Sopenharmony_ci  // Kill the previous elements on {object}.
8031cb0ef41Sopenharmony_ci  state = state->KillField(object,
8041cb0ef41Sopenharmony_ci                           FieldIndexOf(JSObject::kElementsOffset, kTaggedSize),
8051cb0ef41Sopenharmony_ci                           MaybeHandle<Name>(), zone());
8061cb0ef41Sopenharmony_ci  // Add the new elements on {object}.
8071cb0ef41Sopenharmony_ci  state = state->AddField(
8081cb0ef41Sopenharmony_ci      object, FieldIndexOf(JSObject::kElementsOffset, kTaggedSize),
8091cb0ef41Sopenharmony_ci      {node, MachineRepresentation::kTaggedPointer}, zone());
8101cb0ef41Sopenharmony_ci  return UpdateState(node, state);
8111cb0ef41Sopenharmony_ci}
8121cb0ef41Sopenharmony_ci
8131cb0ef41Sopenharmony_ciReduction LoadElimination::ReduceMaybeGrowFastElements(Node* node) {
8141cb0ef41Sopenharmony_ci  GrowFastElementsParameters params = GrowFastElementsParametersOf(node->op());
8151cb0ef41Sopenharmony_ci  Node* const object = NodeProperties::GetValueInput(node, 0);
8161cb0ef41Sopenharmony_ci  Node* const effect = NodeProperties::GetEffectInput(node);
8171cb0ef41Sopenharmony_ci  AbstractState const* state = node_states_.Get(effect);
8181cb0ef41Sopenharmony_ci  if (state == nullptr) return NoChange();
8191cb0ef41Sopenharmony_ci  if (params.mode() == GrowFastElementsMode::kDoubleElements) {
8201cb0ef41Sopenharmony_ci    // We know that the resulting elements have the fixed double array map.
8211cb0ef41Sopenharmony_ci    state = state->SetMaps(
8221cb0ef41Sopenharmony_ci        node, ZoneHandleSet<Map>(factory()->fixed_double_array_map()), zone());
8231cb0ef41Sopenharmony_ci  } else {
8241cb0ef41Sopenharmony_ci    // We know that the resulting elements have the fixed array map or the COW
8251cb0ef41Sopenharmony_ci    // version thereof (if we didn't grow and it was already COW before).
8261cb0ef41Sopenharmony_ci    ZoneHandleSet<Map> fixed_array_maps(factory()->fixed_array_map());
8271cb0ef41Sopenharmony_ci    fixed_array_maps.insert(factory()->fixed_cow_array_map(), zone());
8281cb0ef41Sopenharmony_ci    state = state->SetMaps(node, fixed_array_maps, zone());
8291cb0ef41Sopenharmony_ci  }
8301cb0ef41Sopenharmony_ci  // Kill the previous elements on {object}.
8311cb0ef41Sopenharmony_ci  state = state->KillField(object,
8321cb0ef41Sopenharmony_ci                           FieldIndexOf(JSObject::kElementsOffset, kTaggedSize),
8331cb0ef41Sopenharmony_ci                           MaybeHandle<Name>(), zone());
8341cb0ef41Sopenharmony_ci  // Add the new elements on {object}.
8351cb0ef41Sopenharmony_ci  state = state->AddField(
8361cb0ef41Sopenharmony_ci      object, FieldIndexOf(JSObject::kElementsOffset, kTaggedSize),
8371cb0ef41Sopenharmony_ci      {node, MachineRepresentation::kTaggedPointer}, zone());
8381cb0ef41Sopenharmony_ci  return UpdateState(node, state);
8391cb0ef41Sopenharmony_ci}
8401cb0ef41Sopenharmony_ci
8411cb0ef41Sopenharmony_ciReduction LoadElimination::ReduceTransitionElementsKind(Node* node) {
8421cb0ef41Sopenharmony_ci  ElementsTransition transition = ElementsTransitionOf(node->op());
8431cb0ef41Sopenharmony_ci  Node* const object = NodeProperties::GetValueInput(node, 0);
8441cb0ef41Sopenharmony_ci  Handle<Map> source_map(transition.source());
8451cb0ef41Sopenharmony_ci  Handle<Map> target_map(transition.target());
8461cb0ef41Sopenharmony_ci  Node* const effect = NodeProperties::GetEffectInput(node);
8471cb0ef41Sopenharmony_ci  AbstractState const* state = node_states_.Get(effect);
8481cb0ef41Sopenharmony_ci  if (state == nullptr) return NoChange();
8491cb0ef41Sopenharmony_ci  switch (transition.mode()) {
8501cb0ef41Sopenharmony_ci    case ElementsTransition::kFastTransition:
8511cb0ef41Sopenharmony_ci      break;
8521cb0ef41Sopenharmony_ci    case ElementsTransition::kSlowTransition:
8531cb0ef41Sopenharmony_ci      // Kill the elements as well.
8541cb0ef41Sopenharmony_ci      AliasStateInfo alias_info(state, object, source_map);
8551cb0ef41Sopenharmony_ci      state = state->KillField(
8561cb0ef41Sopenharmony_ci          alias_info, FieldIndexOf(JSObject::kElementsOffset, kTaggedSize),
8571cb0ef41Sopenharmony_ci          MaybeHandle<Name>(), zone());
8581cb0ef41Sopenharmony_ci      break;
8591cb0ef41Sopenharmony_ci  }
8601cb0ef41Sopenharmony_ci  ZoneHandleSet<Map> object_maps;
8611cb0ef41Sopenharmony_ci  if (state->LookupMaps(object, &object_maps)) {
8621cb0ef41Sopenharmony_ci    if (ZoneHandleSet<Map>(target_map).contains(object_maps)) {
8631cb0ef41Sopenharmony_ci      // The {object} already has the {target_map}, so this TransitionElements
8641cb0ef41Sopenharmony_ci      // {node} is fully redundant (independent of what {source_map} is).
8651cb0ef41Sopenharmony_ci      return Replace(effect);
8661cb0ef41Sopenharmony_ci    }
8671cb0ef41Sopenharmony_ci    if (object_maps.contains(ZoneHandleSet<Map>(source_map))) {
8681cb0ef41Sopenharmony_ci      object_maps.remove(source_map, zone());
8691cb0ef41Sopenharmony_ci      object_maps.insert(target_map, zone());
8701cb0ef41Sopenharmony_ci      AliasStateInfo alias_info(state, object, source_map);
8711cb0ef41Sopenharmony_ci      state = state->KillMaps(alias_info, zone());
8721cb0ef41Sopenharmony_ci      state = state->SetMaps(object, object_maps, zone());
8731cb0ef41Sopenharmony_ci    }
8741cb0ef41Sopenharmony_ci  } else {
8751cb0ef41Sopenharmony_ci    AliasStateInfo alias_info(state, object, source_map);
8761cb0ef41Sopenharmony_ci    state = state->KillMaps(alias_info, zone());
8771cb0ef41Sopenharmony_ci  }
8781cb0ef41Sopenharmony_ci  return UpdateState(node, state);
8791cb0ef41Sopenharmony_ci}
8801cb0ef41Sopenharmony_ci
8811cb0ef41Sopenharmony_ciReduction LoadElimination::ReduceTransitionAndStoreElement(Node* node) {
8821cb0ef41Sopenharmony_ci  Node* const object = NodeProperties::GetValueInput(node, 0);
8831cb0ef41Sopenharmony_ci  Handle<Map> double_map(DoubleMapParameterOf(node->op()));
8841cb0ef41Sopenharmony_ci  Handle<Map> fast_map(FastMapParameterOf(node->op()));
8851cb0ef41Sopenharmony_ci  Node* const effect = NodeProperties::GetEffectInput(node);
8861cb0ef41Sopenharmony_ci  AbstractState const* state = node_states_.Get(effect);
8871cb0ef41Sopenharmony_ci  if (state == nullptr) return NoChange();
8881cb0ef41Sopenharmony_ci
8891cb0ef41Sopenharmony_ci  // We need to add the double and fast maps to the set of possible maps for
8901cb0ef41Sopenharmony_ci  // this object, because we don't know which of those we'll transition to.
8911cb0ef41Sopenharmony_ci  // Additionally, we should kill all alias information.
8921cb0ef41Sopenharmony_ci  ZoneHandleSet<Map> object_maps;
8931cb0ef41Sopenharmony_ci  if (state->LookupMaps(object, &object_maps)) {
8941cb0ef41Sopenharmony_ci    object_maps.insert(double_map, zone());
8951cb0ef41Sopenharmony_ci    object_maps.insert(fast_map, zone());
8961cb0ef41Sopenharmony_ci    state = state->KillMaps(object, zone());
8971cb0ef41Sopenharmony_ci    state = state->SetMaps(object, object_maps, zone());
8981cb0ef41Sopenharmony_ci  }
8991cb0ef41Sopenharmony_ci  // Kill the elements as well.
9001cb0ef41Sopenharmony_ci  state = state->KillField(object,
9011cb0ef41Sopenharmony_ci                           FieldIndexOf(JSObject::kElementsOffset, kTaggedSize),
9021cb0ef41Sopenharmony_ci                           MaybeHandle<Name>(), zone());
9031cb0ef41Sopenharmony_ci  return UpdateState(node, state);
9041cb0ef41Sopenharmony_ci}
9051cb0ef41Sopenharmony_ci
9061cb0ef41Sopenharmony_ciReduction LoadElimination::ReduceLoadField(Node* node,
9071cb0ef41Sopenharmony_ci                                           FieldAccess const& access) {
9081cb0ef41Sopenharmony_ci  Node* object = NodeProperties::GetValueInput(node, 0);
9091cb0ef41Sopenharmony_ci  Node* effect = NodeProperties::GetEffectInput(node);
9101cb0ef41Sopenharmony_ci  Node* control = NodeProperties::GetControlInput(node);
9111cb0ef41Sopenharmony_ci  AbstractState const* state = node_states_.Get(effect);
9121cb0ef41Sopenharmony_ci  if (state == nullptr) return NoChange();
9131cb0ef41Sopenharmony_ci  if (access.offset == HeapObject::kMapOffset &&
9141cb0ef41Sopenharmony_ci      access.base_is_tagged == kTaggedBase) {
9151cb0ef41Sopenharmony_ci    DCHECK(IsAnyTagged(access.machine_type.representation()));
9161cb0ef41Sopenharmony_ci    ZoneHandleSet<Map> object_maps;
9171cb0ef41Sopenharmony_ci    if (state->LookupMaps(object, &object_maps) && object_maps.size() == 1) {
9181cb0ef41Sopenharmony_ci      Node* value = jsgraph()->HeapConstant(object_maps[0]);
9191cb0ef41Sopenharmony_ci      NodeProperties::SetType(value, Type::OtherInternal());
9201cb0ef41Sopenharmony_ci      ReplaceWithValue(node, value, effect);
9211cb0ef41Sopenharmony_ci      return Replace(value);
9221cb0ef41Sopenharmony_ci    }
9231cb0ef41Sopenharmony_ci  } else {
9241cb0ef41Sopenharmony_ci    IndexRange field_index = FieldIndexOf(access);
9251cb0ef41Sopenharmony_ci    if (field_index != IndexRange::Invalid()) {
9261cb0ef41Sopenharmony_ci      MachineRepresentation representation =
9271cb0ef41Sopenharmony_ci          access.machine_type.representation();
9281cb0ef41Sopenharmony_ci      FieldInfo const* lookup_result =
9291cb0ef41Sopenharmony_ci          state->LookupField(object, field_index, access.const_field_info);
9301cb0ef41Sopenharmony_ci      if (!lookup_result && access.const_field_info.IsConst()) {
9311cb0ef41Sopenharmony_ci        // If the access is const and we didn't find anything, also try to look
9321cb0ef41Sopenharmony_ci        // up information from mutable stores
9331cb0ef41Sopenharmony_ci        lookup_result =
9341cb0ef41Sopenharmony_ci            state->LookupField(object, field_index, ConstFieldInfo::None());
9351cb0ef41Sopenharmony_ci      }
9361cb0ef41Sopenharmony_ci      if (lookup_result) {
9371cb0ef41Sopenharmony_ci        // Make sure we don't reuse values that were recorded with a different
9381cb0ef41Sopenharmony_ci        // representation or resurrect dead {replacement} nodes.
9391cb0ef41Sopenharmony_ci        Node* replacement = lookup_result->value;
9401cb0ef41Sopenharmony_ci        if (IsCompatible(representation, lookup_result->representation) &&
9411cb0ef41Sopenharmony_ci            !replacement->IsDead()) {
9421cb0ef41Sopenharmony_ci          // Introduce a TypeGuard if the type of the {replacement} node is not
9431cb0ef41Sopenharmony_ci          // a subtype of the original {node}'s type.
9441cb0ef41Sopenharmony_ci          if (!NodeProperties::GetType(replacement)
9451cb0ef41Sopenharmony_ci                   .Is(NodeProperties::GetType(node))) {
9461cb0ef41Sopenharmony_ci            Type replacement_type = Type::Intersect(
9471cb0ef41Sopenharmony_ci                NodeProperties::GetType(node),
9481cb0ef41Sopenharmony_ci                NodeProperties::GetType(replacement), graph()->zone());
9491cb0ef41Sopenharmony_ci            replacement = effect =
9501cb0ef41Sopenharmony_ci                graph()->NewNode(common()->TypeGuard(replacement_type),
9511cb0ef41Sopenharmony_ci                                 replacement, effect, control);
9521cb0ef41Sopenharmony_ci            NodeProperties::SetType(replacement, replacement_type);
9531cb0ef41Sopenharmony_ci          }
9541cb0ef41Sopenharmony_ci          ReplaceWithValue(node, replacement, effect);
9551cb0ef41Sopenharmony_ci          return Replace(replacement);
9561cb0ef41Sopenharmony_ci        }
9571cb0ef41Sopenharmony_ci      }
9581cb0ef41Sopenharmony_ci      FieldInfo info(node, representation, access.name,
9591cb0ef41Sopenharmony_ci                     access.const_field_info);
9601cb0ef41Sopenharmony_ci      state = state->AddField(object, field_index, info, zone());
9611cb0ef41Sopenharmony_ci    }
9621cb0ef41Sopenharmony_ci  }
9631cb0ef41Sopenharmony_ci  Handle<Map> field_map;
9641cb0ef41Sopenharmony_ci  if (access.map.ToHandle(&field_map)) {
9651cb0ef41Sopenharmony_ci    state = state->SetMaps(node, ZoneHandleSet<Map>(field_map), zone());
9661cb0ef41Sopenharmony_ci  }
9671cb0ef41Sopenharmony_ci  return UpdateState(node, state);
9681cb0ef41Sopenharmony_ci}
9691cb0ef41Sopenharmony_ci
9701cb0ef41Sopenharmony_ciReduction LoadElimination::ReduceStoreField(Node* node,
9711cb0ef41Sopenharmony_ci                                            FieldAccess const& access) {
9721cb0ef41Sopenharmony_ci  Node* const object = NodeProperties::GetValueInput(node, 0);
9731cb0ef41Sopenharmony_ci  Node* const new_value = NodeProperties::GetValueInput(node, 1);
9741cb0ef41Sopenharmony_ci  Node* const effect = NodeProperties::GetEffectInput(node);
9751cb0ef41Sopenharmony_ci  AbstractState const* state = node_states_.Get(effect);
9761cb0ef41Sopenharmony_ci  if (state == nullptr) return NoChange();
9771cb0ef41Sopenharmony_ci  if (access.offset == HeapObject::kMapOffset &&
9781cb0ef41Sopenharmony_ci      access.base_is_tagged == kTaggedBase) {
9791cb0ef41Sopenharmony_ci    DCHECK(IsAnyTagged(access.machine_type.representation()));
9801cb0ef41Sopenharmony_ci    // Kill all potential knowledge about the {object}s map.
9811cb0ef41Sopenharmony_ci    state = state->KillMaps(object, zone());
9821cb0ef41Sopenharmony_ci    Type const new_value_type = NodeProperties::GetType(new_value);
9831cb0ef41Sopenharmony_ci    if (new_value_type.IsHeapConstant()) {
9841cb0ef41Sopenharmony_ci      // Record the new {object} map information.
9851cb0ef41Sopenharmony_ci      ZoneHandleSet<Map> object_maps(
9861cb0ef41Sopenharmony_ci          new_value_type.AsHeapConstant()->Ref().AsMap().object());
9871cb0ef41Sopenharmony_ci      state = state->SetMaps(object, object_maps, zone());
9881cb0ef41Sopenharmony_ci    }
9891cb0ef41Sopenharmony_ci  } else {
9901cb0ef41Sopenharmony_ci    IndexRange field_index = FieldIndexOf(access);
9911cb0ef41Sopenharmony_ci    if (field_index != IndexRange::Invalid()) {
9921cb0ef41Sopenharmony_ci      bool is_const_store = access.const_field_info.IsConst();
9931cb0ef41Sopenharmony_ci      MachineRepresentation representation =
9941cb0ef41Sopenharmony_ci          access.machine_type.representation();
9951cb0ef41Sopenharmony_ci      FieldInfo const* lookup_result =
9961cb0ef41Sopenharmony_ci          state->LookupField(object, field_index, access.const_field_info);
9971cb0ef41Sopenharmony_ci
9981cb0ef41Sopenharmony_ci      if (lookup_result &&
9991cb0ef41Sopenharmony_ci          (!is_const_store || V8_ENABLE_DOUBLE_CONST_STORE_CHECK_BOOL)) {
10001cb0ef41Sopenharmony_ci        // At runtime, we should never encounter
10011cb0ef41Sopenharmony_ci        // - any store replacing existing info with a different, incompatible
10021cb0ef41Sopenharmony_ci        //   representation, nor
10031cb0ef41Sopenharmony_ci        // - two consecutive const stores, unless the latter is a store into
10041cb0ef41Sopenharmony_ci        //   a literal.
10051cb0ef41Sopenharmony_ci        // However, we may see such code statically, so we guard against
10061cb0ef41Sopenharmony_ci        // executing it by emitting Unreachable.
10071cb0ef41Sopenharmony_ci        // TODO(gsps): Re-enable the double const store check even for
10081cb0ef41Sopenharmony_ci        //   non-debug builds once we have identified other FieldAccesses
10091cb0ef41Sopenharmony_ci        //   that should be marked mutable instead of const
10101cb0ef41Sopenharmony_ci        //   (cf. JSCreateLowering::AllocateFastLiteral).
10111cb0ef41Sopenharmony_ci        bool incompatible_representation =
10121cb0ef41Sopenharmony_ci            !lookup_result->name.is_null() &&
10131cb0ef41Sopenharmony_ci            !IsCompatible(representation, lookup_result->representation);
10141cb0ef41Sopenharmony_ci        bool illegal_double_const_store =
10151cb0ef41Sopenharmony_ci            is_const_store && !access.is_store_in_literal;
10161cb0ef41Sopenharmony_ci        if (incompatible_representation || illegal_double_const_store) {
10171cb0ef41Sopenharmony_ci          Node* control = NodeProperties::GetControlInput(node);
10181cb0ef41Sopenharmony_ci          Node* unreachable =
10191cb0ef41Sopenharmony_ci              graph()->NewNode(common()->Unreachable(), effect, control);
10201cb0ef41Sopenharmony_ci          return Replace(unreachable);
10211cb0ef41Sopenharmony_ci        }
10221cb0ef41Sopenharmony_ci        if (lookup_result->value == new_value) {
10231cb0ef41Sopenharmony_ci          // This store is fully redundant.
10241cb0ef41Sopenharmony_ci          return Replace(effect);
10251cb0ef41Sopenharmony_ci        }
10261cb0ef41Sopenharmony_ci      }
10271cb0ef41Sopenharmony_ci
10281cb0ef41Sopenharmony_ci      // Kill all potentially aliasing fields and record the new value.
10291cb0ef41Sopenharmony_ci      FieldInfo new_info(new_value, representation, access.name,
10301cb0ef41Sopenharmony_ci                         access.const_field_info);
10311cb0ef41Sopenharmony_ci      if (is_const_store && access.is_store_in_literal) {
10321cb0ef41Sopenharmony_ci        // We only kill const information when there is a chance that we
10331cb0ef41Sopenharmony_ci        // previously stored information about the given const field (namely,
10341cb0ef41Sopenharmony_ci        // when we observe const stores to literals).
10351cb0ef41Sopenharmony_ci        state = state->KillConstField(object, field_index, zone());
10361cb0ef41Sopenharmony_ci      }
10371cb0ef41Sopenharmony_ci      state = state->KillField(object, field_index, access.name, zone());
10381cb0ef41Sopenharmony_ci      state = state->AddField(object, field_index, new_info, zone());
10391cb0ef41Sopenharmony_ci      if (is_const_store) {
10401cb0ef41Sopenharmony_ci        // For const stores, we track information in both the const and the
10411cb0ef41Sopenharmony_ci        // mutable world to guard against field accesses that should have
10421cb0ef41Sopenharmony_ci        // been marked const, but were not.
10431cb0ef41Sopenharmony_ci        new_info.const_field_info = ConstFieldInfo::None();
10441cb0ef41Sopenharmony_ci        state = state->AddField(object, field_index, new_info, zone());
10451cb0ef41Sopenharmony_ci      }
10461cb0ef41Sopenharmony_ci    } else {
10471cb0ef41Sopenharmony_ci      // Unsupported StoreField operator.
10481cb0ef41Sopenharmony_ci      state = state->KillFields(object, access.name, zone());
10491cb0ef41Sopenharmony_ci    }
10501cb0ef41Sopenharmony_ci  }
10511cb0ef41Sopenharmony_ci  return UpdateState(node, state);
10521cb0ef41Sopenharmony_ci}
10531cb0ef41Sopenharmony_ci
10541cb0ef41Sopenharmony_ciReduction LoadElimination::ReduceLoadElement(Node* node) {
10551cb0ef41Sopenharmony_ci  Node* const object = NodeProperties::GetValueInput(node, 0);
10561cb0ef41Sopenharmony_ci  Node* const index = NodeProperties::GetValueInput(node, 1);
10571cb0ef41Sopenharmony_ci  Node* const effect = NodeProperties::GetEffectInput(node);
10581cb0ef41Sopenharmony_ci  AbstractState const* state = node_states_.Get(effect);
10591cb0ef41Sopenharmony_ci  if (state == nullptr) return NoChange();
10601cb0ef41Sopenharmony_ci
10611cb0ef41Sopenharmony_ci  // Only handle loads that do not require truncations.
10621cb0ef41Sopenharmony_ci  ElementAccess const& access = ElementAccessOf(node->op());
10631cb0ef41Sopenharmony_ci  switch (access.machine_type.representation()) {
10641cb0ef41Sopenharmony_ci    case MachineRepresentation::kNone:
10651cb0ef41Sopenharmony_ci    case MachineRepresentation::kBit:
10661cb0ef41Sopenharmony_ci    case MachineRepresentation::kWord8:
10671cb0ef41Sopenharmony_ci    case MachineRepresentation::kWord16:
10681cb0ef41Sopenharmony_ci    case MachineRepresentation::kWord32:
10691cb0ef41Sopenharmony_ci    case MachineRepresentation::kWord64:
10701cb0ef41Sopenharmony_ci    case MachineRepresentation::kFloat32:
10711cb0ef41Sopenharmony_ci    case MachineRepresentation::kCompressedPointer:
10721cb0ef41Sopenharmony_ci    case MachineRepresentation::kCompressed:
10731cb0ef41Sopenharmony_ci    case MachineRepresentation::kSandboxedPointer:
10741cb0ef41Sopenharmony_ci      // TODO(turbofan): Add support for doing the truncations.
10751cb0ef41Sopenharmony_ci      break;
10761cb0ef41Sopenharmony_ci    case MachineRepresentation::kFloat64:
10771cb0ef41Sopenharmony_ci    case MachineRepresentation::kSimd128:
10781cb0ef41Sopenharmony_ci    case MachineRepresentation::kTaggedSigned:
10791cb0ef41Sopenharmony_ci    case MachineRepresentation::kTaggedPointer:
10801cb0ef41Sopenharmony_ci    case MachineRepresentation::kTagged:
10811cb0ef41Sopenharmony_ci    case MachineRepresentation::kMapWord:
10821cb0ef41Sopenharmony_ci      if (Node* replacement = state->LookupElement(
10831cb0ef41Sopenharmony_ci              object, index, access.machine_type.representation())) {
10841cb0ef41Sopenharmony_ci        // Make sure we don't resurrect dead {replacement} nodes.
10851cb0ef41Sopenharmony_ci        // Skip lowering if the type of the {replacement} node is not a subtype
10861cb0ef41Sopenharmony_ci        // of the original {node}'s type.
10871cb0ef41Sopenharmony_ci        // TODO(turbofan): We should insert a {TypeGuard} for the intersection
10881cb0ef41Sopenharmony_ci        // of these two types here once we properly handle {Type::None}
10891cb0ef41Sopenharmony_ci        // everywhere.
10901cb0ef41Sopenharmony_ci        if (!replacement->IsDead() && NodeProperties::GetType(replacement)
10911cb0ef41Sopenharmony_ci                                          .Is(NodeProperties::GetType(node))) {
10921cb0ef41Sopenharmony_ci          ReplaceWithValue(node, replacement, effect);
10931cb0ef41Sopenharmony_ci          return Replace(replacement);
10941cb0ef41Sopenharmony_ci        }
10951cb0ef41Sopenharmony_ci      }
10961cb0ef41Sopenharmony_ci      state = state->AddElement(object, index, node,
10971cb0ef41Sopenharmony_ci                                access.machine_type.representation(), zone());
10981cb0ef41Sopenharmony_ci      return UpdateState(node, state);
10991cb0ef41Sopenharmony_ci  }
11001cb0ef41Sopenharmony_ci  return NoChange();
11011cb0ef41Sopenharmony_ci}
11021cb0ef41Sopenharmony_ci
11031cb0ef41Sopenharmony_ciReduction LoadElimination::ReduceStoreElement(Node* node) {
11041cb0ef41Sopenharmony_ci  ElementAccess const& access = ElementAccessOf(node->op());
11051cb0ef41Sopenharmony_ci  Node* const object = NodeProperties::GetValueInput(node, 0);
11061cb0ef41Sopenharmony_ci  Node* const index = NodeProperties::GetValueInput(node, 1);
11071cb0ef41Sopenharmony_ci  Node* const new_value = NodeProperties::GetValueInput(node, 2);
11081cb0ef41Sopenharmony_ci  Node* const effect = NodeProperties::GetEffectInput(node);
11091cb0ef41Sopenharmony_ci  AbstractState const* state = node_states_.Get(effect);
11101cb0ef41Sopenharmony_ci  if (state == nullptr) return NoChange();
11111cb0ef41Sopenharmony_ci  Node* const old_value =
11121cb0ef41Sopenharmony_ci      state->LookupElement(object, index, access.machine_type.representation());
11131cb0ef41Sopenharmony_ci  if (old_value == new_value) {
11141cb0ef41Sopenharmony_ci    // This store is fully redundant.
11151cb0ef41Sopenharmony_ci    return Replace(effect);
11161cb0ef41Sopenharmony_ci  }
11171cb0ef41Sopenharmony_ci  // Kill all potentially aliasing elements.
11181cb0ef41Sopenharmony_ci  state = state->KillElement(object, index, zone());
11191cb0ef41Sopenharmony_ci  // Only record the new value if the store doesn't have an implicit truncation.
11201cb0ef41Sopenharmony_ci  switch (access.machine_type.representation()) {
11211cb0ef41Sopenharmony_ci    case MachineRepresentation::kNone:
11221cb0ef41Sopenharmony_ci    case MachineRepresentation::kBit:
11231cb0ef41Sopenharmony_ci    case MachineRepresentation::kWord8:
11241cb0ef41Sopenharmony_ci    case MachineRepresentation::kWord16:
11251cb0ef41Sopenharmony_ci    case MachineRepresentation::kWord32:
11261cb0ef41Sopenharmony_ci    case MachineRepresentation::kWord64:
11271cb0ef41Sopenharmony_ci    case MachineRepresentation::kFloat32:
11281cb0ef41Sopenharmony_ci    case MachineRepresentation::kCompressedPointer:
11291cb0ef41Sopenharmony_ci    case MachineRepresentation::kCompressed:
11301cb0ef41Sopenharmony_ci    case MachineRepresentation::kSandboxedPointer:
11311cb0ef41Sopenharmony_ci      // TODO(turbofan): Add support for doing the truncations.
11321cb0ef41Sopenharmony_ci      break;
11331cb0ef41Sopenharmony_ci    case MachineRepresentation::kFloat64:
11341cb0ef41Sopenharmony_ci    case MachineRepresentation::kSimd128:
11351cb0ef41Sopenharmony_ci    case MachineRepresentation::kTaggedSigned:
11361cb0ef41Sopenharmony_ci    case MachineRepresentation::kTaggedPointer:
11371cb0ef41Sopenharmony_ci    case MachineRepresentation::kTagged:
11381cb0ef41Sopenharmony_ci    case MachineRepresentation::kMapWord:
11391cb0ef41Sopenharmony_ci      state = state->AddElement(object, index, new_value,
11401cb0ef41Sopenharmony_ci                                access.machine_type.representation(), zone());
11411cb0ef41Sopenharmony_ci      break;
11421cb0ef41Sopenharmony_ci  }
11431cb0ef41Sopenharmony_ci  return UpdateState(node, state);
11441cb0ef41Sopenharmony_ci}
11451cb0ef41Sopenharmony_ci
11461cb0ef41Sopenharmony_ciReduction LoadElimination::ReduceStoreTypedElement(Node* node) {
11471cb0ef41Sopenharmony_ci  Node* const effect = NodeProperties::GetEffectInput(node);
11481cb0ef41Sopenharmony_ci  AbstractState const* state = node_states_.Get(effect);
11491cb0ef41Sopenharmony_ci  if (state == nullptr) return NoChange();
11501cb0ef41Sopenharmony_ci  return UpdateState(node, state);
11511cb0ef41Sopenharmony_ci}
11521cb0ef41Sopenharmony_ci
11531cb0ef41Sopenharmony_ciLoadElimination::AbstractState const* LoadElimination::UpdateStateForPhi(
11541cb0ef41Sopenharmony_ci    AbstractState const* state, Node* effect_phi, Node* phi) {
11551cb0ef41Sopenharmony_ci  int predecessor_count = phi->InputCount() - 1;
11561cb0ef41Sopenharmony_ci  // TODO(jarin) Consider doing a union here. At the moment, we just keep this
11571cb0ef41Sopenharmony_ci  // consistent with AbstractState::Merge.
11581cb0ef41Sopenharmony_ci
11591cb0ef41Sopenharmony_ci  // Check if all the inputs have the same maps.
11601cb0ef41Sopenharmony_ci  AbstractState const* input_state =
11611cb0ef41Sopenharmony_ci      node_states_.Get(NodeProperties::GetEffectInput(effect_phi, 0));
11621cb0ef41Sopenharmony_ci  ZoneHandleSet<Map> object_maps;
11631cb0ef41Sopenharmony_ci  if (!input_state->LookupMaps(phi->InputAt(0), &object_maps)) return state;
11641cb0ef41Sopenharmony_ci  for (int i = 1; i < predecessor_count; i++) {
11651cb0ef41Sopenharmony_ci    input_state =
11661cb0ef41Sopenharmony_ci        node_states_.Get(NodeProperties::GetEffectInput(effect_phi, i));
11671cb0ef41Sopenharmony_ci    ZoneHandleSet<Map> input_maps;
11681cb0ef41Sopenharmony_ci    if (!input_state->LookupMaps(phi->InputAt(i), &input_maps)) return state;
11691cb0ef41Sopenharmony_ci    if (input_maps != object_maps) return state;
11701cb0ef41Sopenharmony_ci  }
11711cb0ef41Sopenharmony_ci  return state->SetMaps(phi, object_maps, zone());
11721cb0ef41Sopenharmony_ci}
11731cb0ef41Sopenharmony_ci
11741cb0ef41Sopenharmony_ciReduction LoadElimination::ReduceEffectPhi(Node* node) {
11751cb0ef41Sopenharmony_ci  Node* const effect0 = NodeProperties::GetEffectInput(node, 0);
11761cb0ef41Sopenharmony_ci  Node* const control = NodeProperties::GetControlInput(node);
11771cb0ef41Sopenharmony_ci  AbstractState const* state0 = node_states_.Get(effect0);
11781cb0ef41Sopenharmony_ci  if (state0 == nullptr) return NoChange();
11791cb0ef41Sopenharmony_ci  if (control->opcode() == IrOpcode::kLoop) {
11801cb0ef41Sopenharmony_ci    // Here we rely on having only reducible loops:
11811cb0ef41Sopenharmony_ci    // The loop entry edge always dominates the header, so we can just take
11821cb0ef41Sopenharmony_ci    // the state from the first input, and compute the loop state based on it.
11831cb0ef41Sopenharmony_ci    AbstractState const* state = ComputeLoopState(node, state0);
11841cb0ef41Sopenharmony_ci    return UpdateState(node, state);
11851cb0ef41Sopenharmony_ci  }
11861cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kMerge, control->opcode());
11871cb0ef41Sopenharmony_ci
11881cb0ef41Sopenharmony_ci  // Shortcut for the case when we do not know anything about some input.
11891cb0ef41Sopenharmony_ci  int const input_count = node->op()->EffectInputCount();
11901cb0ef41Sopenharmony_ci  for (int i = 1; i < input_count; ++i) {
11911cb0ef41Sopenharmony_ci    Node* const effect = NodeProperties::GetEffectInput(node, i);
11921cb0ef41Sopenharmony_ci    if (node_states_.Get(effect) == nullptr) return NoChange();
11931cb0ef41Sopenharmony_ci  }
11941cb0ef41Sopenharmony_ci
11951cb0ef41Sopenharmony_ci  // Make a copy of the first input's state and merge with the state
11961cb0ef41Sopenharmony_ci  // from other inputs.
11971cb0ef41Sopenharmony_ci  AbstractState* state = zone()->New<AbstractState>(*state0);
11981cb0ef41Sopenharmony_ci  for (int i = 1; i < input_count; ++i) {
11991cb0ef41Sopenharmony_ci    Node* const input = NodeProperties::GetEffectInput(node, i);
12001cb0ef41Sopenharmony_ci    state->Merge(node_states_.Get(input), zone());
12011cb0ef41Sopenharmony_ci  }
12021cb0ef41Sopenharmony_ci
12031cb0ef41Sopenharmony_ci  // For each phi, try to compute the new state for the phi from
12041cb0ef41Sopenharmony_ci  // the inputs.
12051cb0ef41Sopenharmony_ci  AbstractState const* state_with_phis = state;
12061cb0ef41Sopenharmony_ci  for (Node* use : control->uses()) {
12071cb0ef41Sopenharmony_ci    if (use->opcode() == IrOpcode::kPhi) {
12081cb0ef41Sopenharmony_ci      state_with_phis = UpdateStateForPhi(state_with_phis, node, use);
12091cb0ef41Sopenharmony_ci    }
12101cb0ef41Sopenharmony_ci  }
12111cb0ef41Sopenharmony_ci
12121cb0ef41Sopenharmony_ci  return UpdateState(node, state_with_phis);
12131cb0ef41Sopenharmony_ci}
12141cb0ef41Sopenharmony_ci
12151cb0ef41Sopenharmony_ciReduction LoadElimination::ReduceStart(Node* node) {
12161cb0ef41Sopenharmony_ci  return UpdateState(node, empty_state());
12171cb0ef41Sopenharmony_ci}
12181cb0ef41Sopenharmony_ci
12191cb0ef41Sopenharmony_ciReduction LoadElimination::ReduceOtherNode(Node* node) {
12201cb0ef41Sopenharmony_ci  if (node->op()->EffectInputCount() == 1) {
12211cb0ef41Sopenharmony_ci    if (node->op()->EffectOutputCount() == 1) {
12221cb0ef41Sopenharmony_ci      Node* const effect = NodeProperties::GetEffectInput(node);
12231cb0ef41Sopenharmony_ci      AbstractState const* state = node_states_.Get(effect);
12241cb0ef41Sopenharmony_ci      // If we do not know anything about the predecessor, do not propagate
12251cb0ef41Sopenharmony_ci      // just yet because we will have to recompute anyway once we compute
12261cb0ef41Sopenharmony_ci      // the predecessor.
12271cb0ef41Sopenharmony_ci      if (state == nullptr) return NoChange();
12281cb0ef41Sopenharmony_ci      // Check if this {node} has some uncontrolled side effects.
12291cb0ef41Sopenharmony_ci      if (!node->op()->HasProperty(Operator::kNoWrite)) {
12301cb0ef41Sopenharmony_ci        state = state->KillAll(zone());
12311cb0ef41Sopenharmony_ci      }
12321cb0ef41Sopenharmony_ci      return UpdateState(node, state);
12331cb0ef41Sopenharmony_ci    } else {
12341cb0ef41Sopenharmony_ci      // Effect terminators should be handled specially.
12351cb0ef41Sopenharmony_ci      return NoChange();
12361cb0ef41Sopenharmony_ci    }
12371cb0ef41Sopenharmony_ci  }
12381cb0ef41Sopenharmony_ci  DCHECK_EQ(0, node->op()->EffectInputCount());
12391cb0ef41Sopenharmony_ci  DCHECK_EQ(0, node->op()->EffectOutputCount());
12401cb0ef41Sopenharmony_ci  return NoChange();
12411cb0ef41Sopenharmony_ci}
12421cb0ef41Sopenharmony_ci
12431cb0ef41Sopenharmony_ciReduction LoadElimination::UpdateState(Node* node, AbstractState const* state) {
12441cb0ef41Sopenharmony_ci  AbstractState const* original = node_states_.Get(node);
12451cb0ef41Sopenharmony_ci  // Only signal that the {node} has Changed, if the information about {state}
12461cb0ef41Sopenharmony_ci  // has changed wrt. the {original}.
12471cb0ef41Sopenharmony_ci  if (state != original) {
12481cb0ef41Sopenharmony_ci    if (original == nullptr || !state->Equals(original)) {
12491cb0ef41Sopenharmony_ci      node_states_.Set(node, state);
12501cb0ef41Sopenharmony_ci      return Changed(node);
12511cb0ef41Sopenharmony_ci    }
12521cb0ef41Sopenharmony_ci  }
12531cb0ef41Sopenharmony_ci  return NoChange();
12541cb0ef41Sopenharmony_ci}
12551cb0ef41Sopenharmony_ci
12561cb0ef41Sopenharmony_ciLoadElimination::AbstractState const*
12571cb0ef41Sopenharmony_ciLoadElimination::ComputeLoopStateForStoreField(
12581cb0ef41Sopenharmony_ci    Node* current, LoadElimination::AbstractState const* state,
12591cb0ef41Sopenharmony_ci    FieldAccess const& access) const {
12601cb0ef41Sopenharmony_ci  Node* const object = NodeProperties::GetValueInput(current, 0);
12611cb0ef41Sopenharmony_ci  if (access.offset == HeapObject::kMapOffset) {
12621cb0ef41Sopenharmony_ci    // Invalidate what we know about the {object}s map.
12631cb0ef41Sopenharmony_ci    state = state->KillMaps(object, zone());
12641cb0ef41Sopenharmony_ci  } else {
12651cb0ef41Sopenharmony_ci    IndexRange field_index = FieldIndexOf(access);
12661cb0ef41Sopenharmony_ci    if (field_index == IndexRange::Invalid()) {
12671cb0ef41Sopenharmony_ci      state = state->KillFields(object, access.name, zone());
12681cb0ef41Sopenharmony_ci    } else {
12691cb0ef41Sopenharmony_ci      state = state->KillField(object, field_index, access.name, zone());
12701cb0ef41Sopenharmony_ci    }
12711cb0ef41Sopenharmony_ci  }
12721cb0ef41Sopenharmony_ci  return state;
12731cb0ef41Sopenharmony_ci}
12741cb0ef41Sopenharmony_ci
12751cb0ef41Sopenharmony_ciLoadElimination::AbstractState const* LoadElimination::ComputeLoopState(
12761cb0ef41Sopenharmony_ci    Node* node, AbstractState const* state) const {
12771cb0ef41Sopenharmony_ci  Node* const control = NodeProperties::GetControlInput(node);
12781cb0ef41Sopenharmony_ci  struct TransitionElementsKindInfo {
12791cb0ef41Sopenharmony_ci    ElementsTransition transition;
12801cb0ef41Sopenharmony_ci    Node* object;
12811cb0ef41Sopenharmony_ci  };
12821cb0ef41Sopenharmony_ci  // Allocate zone data structures in a temporary zone with a lifetime limited
12831cb0ef41Sopenharmony_ci  // to this function to avoid blowing up the size of the stage-global zone.
12841cb0ef41Sopenharmony_ci  Zone temp_zone(zone()->allocator(), "Temporary scoped zone");
12851cb0ef41Sopenharmony_ci  ZoneVector<TransitionElementsKindInfo> element_transitions_(&temp_zone);
12861cb0ef41Sopenharmony_ci  ZoneQueue<Node*> queue(&temp_zone);
12871cb0ef41Sopenharmony_ci  ZoneSet<Node*> visited(&temp_zone);
12881cb0ef41Sopenharmony_ci  visited.insert(node);
12891cb0ef41Sopenharmony_ci  for (int i = 1; i < control->InputCount(); ++i) {
12901cb0ef41Sopenharmony_ci    queue.push(node->InputAt(i));
12911cb0ef41Sopenharmony_ci  }
12921cb0ef41Sopenharmony_ci  while (!queue.empty()) {
12931cb0ef41Sopenharmony_ci    Node* const current = queue.front();
12941cb0ef41Sopenharmony_ci    queue.pop();
12951cb0ef41Sopenharmony_ci    if (visited.find(current) == visited.end()) {
12961cb0ef41Sopenharmony_ci      visited.insert(current);
12971cb0ef41Sopenharmony_ci      if (!current->op()->HasProperty(Operator::kNoWrite)) {
12981cb0ef41Sopenharmony_ci        switch (current->opcode()) {
12991cb0ef41Sopenharmony_ci          case IrOpcode::kEnsureWritableFastElements: {
13001cb0ef41Sopenharmony_ci            Node* const object = NodeProperties::GetValueInput(current, 0);
13011cb0ef41Sopenharmony_ci            state = state->KillField(
13021cb0ef41Sopenharmony_ci                object, FieldIndexOf(JSObject::kElementsOffset, kTaggedSize),
13031cb0ef41Sopenharmony_ci                MaybeHandle<Name>(), zone());
13041cb0ef41Sopenharmony_ci            break;
13051cb0ef41Sopenharmony_ci          }
13061cb0ef41Sopenharmony_ci          case IrOpcode::kMaybeGrowFastElements: {
13071cb0ef41Sopenharmony_ci            Node* const object = NodeProperties::GetValueInput(current, 0);
13081cb0ef41Sopenharmony_ci            state = state->KillField(
13091cb0ef41Sopenharmony_ci                object, FieldIndexOf(JSObject::kElementsOffset, kTaggedSize),
13101cb0ef41Sopenharmony_ci                MaybeHandle<Name>(), zone());
13111cb0ef41Sopenharmony_ci            break;
13121cb0ef41Sopenharmony_ci          }
13131cb0ef41Sopenharmony_ci          case IrOpcode::kTransitionElementsKind: {
13141cb0ef41Sopenharmony_ci            ElementsTransition transition = ElementsTransitionOf(current->op());
13151cb0ef41Sopenharmony_ci            Node* const object = NodeProperties::GetValueInput(current, 0);
13161cb0ef41Sopenharmony_ci            ZoneHandleSet<Map> object_maps;
13171cb0ef41Sopenharmony_ci            if (!state->LookupMaps(object, &object_maps) ||
13181cb0ef41Sopenharmony_ci                !ZoneHandleSet<Map>(transition.target())
13191cb0ef41Sopenharmony_ci                     .contains(object_maps)) {
13201cb0ef41Sopenharmony_ci              element_transitions_.push_back({transition, object});
13211cb0ef41Sopenharmony_ci            }
13221cb0ef41Sopenharmony_ci            break;
13231cb0ef41Sopenharmony_ci          }
13241cb0ef41Sopenharmony_ci          case IrOpcode::kTransitionAndStoreElement: {
13251cb0ef41Sopenharmony_ci            Node* const object = NodeProperties::GetValueInput(current, 0);
13261cb0ef41Sopenharmony_ci            // Invalidate what we know about the {object}s map.
13271cb0ef41Sopenharmony_ci            state = state->KillMaps(object, zone());
13281cb0ef41Sopenharmony_ci            // Kill the elements as well.
13291cb0ef41Sopenharmony_ci            state = state->KillField(
13301cb0ef41Sopenharmony_ci                object, FieldIndexOf(JSObject::kElementsOffset, kTaggedSize),
13311cb0ef41Sopenharmony_ci                MaybeHandle<Name>(), zone());
13321cb0ef41Sopenharmony_ci            break;
13331cb0ef41Sopenharmony_ci          }
13341cb0ef41Sopenharmony_ci          case IrOpcode::kStoreField: {
13351cb0ef41Sopenharmony_ci            FieldAccess access = FieldAccessOf(current->op());
13361cb0ef41Sopenharmony_ci            state = ComputeLoopStateForStoreField(current, state, access);
13371cb0ef41Sopenharmony_ci            break;
13381cb0ef41Sopenharmony_ci          }
13391cb0ef41Sopenharmony_ci          case IrOpcode::kStoreElement: {
13401cb0ef41Sopenharmony_ci            Node* const object = NodeProperties::GetValueInput(current, 0);
13411cb0ef41Sopenharmony_ci            Node* const index = NodeProperties::GetValueInput(current, 1);
13421cb0ef41Sopenharmony_ci            state = state->KillElement(object, index, zone());
13431cb0ef41Sopenharmony_ci            break;
13441cb0ef41Sopenharmony_ci          }
13451cb0ef41Sopenharmony_ci          case IrOpcode::kStoreTypedElement: {
13461cb0ef41Sopenharmony_ci            // Doesn't affect anything we track with the state currently.
13471cb0ef41Sopenharmony_ci            break;
13481cb0ef41Sopenharmony_ci          }
13491cb0ef41Sopenharmony_ci          default:
13501cb0ef41Sopenharmony_ci            return state->KillAll(zone());
13511cb0ef41Sopenharmony_ci        }
13521cb0ef41Sopenharmony_ci      }
13531cb0ef41Sopenharmony_ci      for (int i = 0; i < current->op()->EffectInputCount(); ++i) {
13541cb0ef41Sopenharmony_ci        queue.push(NodeProperties::GetEffectInput(current, i));
13551cb0ef41Sopenharmony_ci      }
13561cb0ef41Sopenharmony_ci    }
13571cb0ef41Sopenharmony_ci  }
13581cb0ef41Sopenharmony_ci
13591cb0ef41Sopenharmony_ci  // Finally, we apply the element transitions. For each transition, we will try
13601cb0ef41Sopenharmony_ci  // to only invalidate information about nodes that can have the transition's
13611cb0ef41Sopenharmony_ci  // source map. The trouble is that an object can be transitioned by some other
13621cb0ef41Sopenharmony_ci  // transition to the source map. In that case, the other transition will
13631cb0ef41Sopenharmony_ci  // invalidate the information, so we are mostly fine.
13641cb0ef41Sopenharmony_ci  //
13651cb0ef41Sopenharmony_ci  // The only bad case is
13661cb0ef41Sopenharmony_ci  //
13671cb0ef41Sopenharmony_ci  //    mapA   ---fast--->   mapB   ---slow--->   mapC
13681cb0ef41Sopenharmony_ci  //
13691cb0ef41Sopenharmony_ci  // If we process the slow transition first on an object that has mapA, we will
13701cb0ef41Sopenharmony_ci  // ignore the transition because the object does not have its source map
13711cb0ef41Sopenharmony_ci  // (mapB). When we later process the fast transition, we invalidate the
13721cb0ef41Sopenharmony_ci  // object's map, but we keep the information about the object's elements. This
13731cb0ef41Sopenharmony_ci  // is wrong because the elements will be overwritten by the slow transition.
13741cb0ef41Sopenharmony_ci  //
13751cb0ef41Sopenharmony_ci  // Note that the slow-slow case is fine because either of the slow transition
13761cb0ef41Sopenharmony_ci  // will invalidate the elements field, so the processing order does not
13771cb0ef41Sopenharmony_ci  // matter.
13781cb0ef41Sopenharmony_ci  //
13791cb0ef41Sopenharmony_ci  // To handle the bad case properly, we first kill the maps using all
13801cb0ef41Sopenharmony_ci  // transitions. We kill the the fields later when all the transitions are
13811cb0ef41Sopenharmony_ci  // already reflected in the map information.
13821cb0ef41Sopenharmony_ci
13831cb0ef41Sopenharmony_ci  for (const TransitionElementsKindInfo& t : element_transitions_) {
13841cb0ef41Sopenharmony_ci    AliasStateInfo alias_info(state, t.object, t.transition.source());
13851cb0ef41Sopenharmony_ci    state = state->KillMaps(alias_info, zone());
13861cb0ef41Sopenharmony_ci  }
13871cb0ef41Sopenharmony_ci  for (const TransitionElementsKindInfo& t : element_transitions_) {
13881cb0ef41Sopenharmony_ci    switch (t.transition.mode()) {
13891cb0ef41Sopenharmony_ci      case ElementsTransition::kFastTransition:
13901cb0ef41Sopenharmony_ci        break;
13911cb0ef41Sopenharmony_ci      case ElementsTransition::kSlowTransition: {
13921cb0ef41Sopenharmony_ci        AliasStateInfo alias_info(state, t.object, t.transition.source());
13931cb0ef41Sopenharmony_ci        state = state->KillField(
13941cb0ef41Sopenharmony_ci            alias_info, FieldIndexOf(JSObject::kElementsOffset, kTaggedSize),
13951cb0ef41Sopenharmony_ci            MaybeHandle<Name>(), zone());
13961cb0ef41Sopenharmony_ci        break;
13971cb0ef41Sopenharmony_ci      }
13981cb0ef41Sopenharmony_ci    }
13991cb0ef41Sopenharmony_ci  }
14001cb0ef41Sopenharmony_ci  return state;
14011cb0ef41Sopenharmony_ci}
14021cb0ef41Sopenharmony_ci
14031cb0ef41Sopenharmony_ci// static
14041cb0ef41Sopenharmony_ciLoadElimination::IndexRange LoadElimination::FieldIndexOf(
14051cb0ef41Sopenharmony_ci    int offset, int representation_size) {
14061cb0ef41Sopenharmony_ci  DCHECK(IsAligned(offset, kTaggedSize));
14071cb0ef41Sopenharmony_ci  int field_index = offset / kTaggedSize - 1;
14081cb0ef41Sopenharmony_ci  DCHECK_EQ(0, representation_size % kTaggedSize);
14091cb0ef41Sopenharmony_ci  return IndexRange(field_index, representation_size / kTaggedSize);
14101cb0ef41Sopenharmony_ci}
14111cb0ef41Sopenharmony_ci
14121cb0ef41Sopenharmony_ci// static
14131cb0ef41Sopenharmony_ciLoadElimination::IndexRange LoadElimination::FieldIndexOf(
14141cb0ef41Sopenharmony_ci    FieldAccess const& access) {
14151cb0ef41Sopenharmony_ci  MachineRepresentation rep = access.machine_type.representation();
14161cb0ef41Sopenharmony_ci  switch (rep) {
14171cb0ef41Sopenharmony_ci    case MachineRepresentation::kNone:
14181cb0ef41Sopenharmony_ci    case MachineRepresentation::kBit:
14191cb0ef41Sopenharmony_ci    case MachineRepresentation::kSimd128:
14201cb0ef41Sopenharmony_ci      UNREACHABLE();
14211cb0ef41Sopenharmony_ci    case MachineRepresentation::kWord8:
14221cb0ef41Sopenharmony_ci    case MachineRepresentation::kWord16:
14231cb0ef41Sopenharmony_ci    case MachineRepresentation::kFloat32:
14241cb0ef41Sopenharmony_ci      // Currently untracked.
14251cb0ef41Sopenharmony_ci      return IndexRange::Invalid();
14261cb0ef41Sopenharmony_ci    case MachineRepresentation::kFloat64:
14271cb0ef41Sopenharmony_ci    case MachineRepresentation::kWord32:
14281cb0ef41Sopenharmony_ci    case MachineRepresentation::kWord64:
14291cb0ef41Sopenharmony_ci    case MachineRepresentation::kTaggedSigned:
14301cb0ef41Sopenharmony_ci    case MachineRepresentation::kTaggedPointer:
14311cb0ef41Sopenharmony_ci    case MachineRepresentation::kTagged:
14321cb0ef41Sopenharmony_ci    case MachineRepresentation::kMapWord:
14331cb0ef41Sopenharmony_ci    case MachineRepresentation::kCompressedPointer:
14341cb0ef41Sopenharmony_ci    case MachineRepresentation::kCompressed:
14351cb0ef41Sopenharmony_ci    case MachineRepresentation::kSandboxedPointer:
14361cb0ef41Sopenharmony_ci      break;
14371cb0ef41Sopenharmony_ci  }
14381cb0ef41Sopenharmony_ci  int representation_size = ElementSizeInBytes(rep);
14391cb0ef41Sopenharmony_ci  // We currently only track fields that are at least tagged pointer sized.
14401cb0ef41Sopenharmony_ci  if (representation_size < kTaggedSize) return IndexRange::Invalid();
14411cb0ef41Sopenharmony_ci  DCHECK_EQ(0, representation_size % kTaggedSize);
14421cb0ef41Sopenharmony_ci
14431cb0ef41Sopenharmony_ci  if (access.base_is_tagged != kTaggedBase) {
14441cb0ef41Sopenharmony_ci    // We currently only track tagged objects.
14451cb0ef41Sopenharmony_ci    return IndexRange::Invalid();
14461cb0ef41Sopenharmony_ci  }
14471cb0ef41Sopenharmony_ci  return FieldIndexOf(access.offset, representation_size);
14481cb0ef41Sopenharmony_ci}
14491cb0ef41Sopenharmony_ci
14501cb0ef41Sopenharmony_ciCommonOperatorBuilder* LoadElimination::common() const {
14511cb0ef41Sopenharmony_ci  return jsgraph()->common();
14521cb0ef41Sopenharmony_ci}
14531cb0ef41Sopenharmony_ci
14541cb0ef41Sopenharmony_ciGraph* LoadElimination::graph() const { return jsgraph()->graph(); }
14551cb0ef41Sopenharmony_ci
14561cb0ef41Sopenharmony_ciIsolate* LoadElimination::isolate() const { return jsgraph()->isolate(); }
14571cb0ef41Sopenharmony_ci
14581cb0ef41Sopenharmony_ciFactory* LoadElimination::factory() const { return jsgraph()->factory(); }
14591cb0ef41Sopenharmony_ci
14601cb0ef41Sopenharmony_ci}  // namespace compiler
14611cb0ef41Sopenharmony_ci}  // namespace internal
14621cb0ef41Sopenharmony_ci}  // namespace v8
1463