// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:js_runtime/synced/array_flags.dart' show ArrayFlags;

import '../common.dart';
import '../common/codegen.dart' show CodegenRegistry;
import '../common/elements.dart' show JCommonElements;
import '../common/names.dart' show Selectors;
import '../common/tasks.dart' show CompilerTask;
import '../constants/constant_system.dart' as constant_system;
import '../constants/values.dart';
import '../elements/entities.dart';
import '../elements/names.dart';
import '../elements/types.dart';
import '../inferrer/abstract_value_domain.dart';
import '../inferrer/types.dart';
import '../ir/util.dart';
import '../js_backend/field_analysis.dart'
    show FieldAnalysisData, JFieldAnalysis;
import '../js_backend/codegen_inputs.dart' show CodegenInputs;
import '../js_backend/native_data.dart' show NativeData;
import '../js_model/js_world.dart' show JClosedWorld;
import '../js_model/type_recipe.dart'
    show
        TypeEnvironmentStructure,
        TypeExpressionRecipe,
        TypeRecipeDomain,
        TypeRecipeDomainImpl;
import '../js_backend/specialized_checks.dart';
import '../native/behavior.dart';
import '../options.dart';
import '../universe/call_structure.dart';
import '../universe/selector.dart' show Selector;
import '../universe/side_effects.dart' show SideEffects;
import '../universe/use.dart' show StaticUse;
import '../util/bitset.dart';
import '../util/util.dart';
import 'interceptor_simplifier.dart';
import 'interceptor_finalizer.dart';
import 'late_field_optimizer.dart';
import 'logging.dart';
import 'nodes.dart';
import 'metrics.dart';
import 'types.dart';
import 'types_propagation.dart';
import 'validate.dart' show NoUnusedPhiValidator;
import 'value_range_analyzer.dart';
import 'value_set.dart';

abstract class OptimizationPhase {
  String get name;
  void visitGraph(HGraph graph);
  bool validPostcondition(HGraph graph);
}

class SsaOptimizerTask extends CompilerTask {
  final CompilerOptions _options;

  Map<HInstruction, Range> ranges = {};

  final Map<MemberEntity, OptimizationTestLog> loggersForTesting = {};

  SsaOptimizerTask(super.measurer, this._options);

  @override
  String get name => 'SSA optimizer';

  void optimize(
    MemberEntity member,
    HGraph graph,
    CodegenInputs codegen,
    JClosedWorld closedWorld,
    GlobalTypeInferenceResults globalInferenceResults,
    CodegenRegistry registry,
    SsaMetrics metrics,
  ) {
    void runPhase(OptimizationPhase phase) {
      measureSubtask(phase.name, () => phase.visitGraph(graph));
      codegen.tracer.traceGraph(phase.name, graph);
      assert(graph.isValid(), 'Graph not valid after ${phase.name}');
      assert(
        phase.validPostcondition(graph),
        'Graph does not satisfy phase postcondition after ${phase.name}',
      );
    }

    SsaCodeMotion codeMotion;
    SsaLoadElimination loadElimination;

    TypeRecipeDomain typeRecipeDomain = TypeRecipeDomainImpl(
      closedWorld.dartTypes,
    );

    OptimizationTestLog? log;
    if (retainDataForTesting) {
      log = loggersForTesting[member] = OptimizationTestLog(
        closedWorld.dartTypes,
      );
    }

    measure(() {
      List<OptimizationPhase> phases = [
        // Run trivial instruction simplification first to optimize some
        // patterns useful for type conversion.
        SsaInstructionSimplifier(
          globalInferenceResults,
          _options,
          closedWorld,
          typeRecipeDomain,
          registry,
          log,
          metrics,
          beforeTypePropagation: true,
        ),
        SsaTypeConversionInserter(closedWorld),
        SsaRedundantPhiEliminator(),
        SsaDeadPhiEliminator(),
        SsaTypePropagator(
          globalInferenceResults,
          closedWorld.commonElements,
          closedWorld,
          log,
        ),
        // After type propagation, more instructions can be simplified.
        SsaInstructionSimplifier(
          globalInferenceResults,
          _options,
          closedWorld,
          typeRecipeDomain,
          registry,
          log,
          metrics,
        ),
        SsaInstructionSimplifier(
          globalInferenceResults,
          _options,
          closedWorld,
          typeRecipeDomain,
          registry,
          log,
          metrics,
        ),
        SsaTypePropagator(
          globalInferenceResults,
          closedWorld.commonElements,
          closedWorld,
          log,
        ),
        // Run a dead code eliminator before LICM because dead
        // interceptors are often in the way of LICM'able instructions.
        SsaDeadCodeEliminator(closedWorld, this),
        SsaGlobalValueNumberer(closedWorld.abstractValueDomain),
        // After GVN, some instructions might need their type to be
        // updated because they now have different inputs.
        SsaTypePropagator(
          globalInferenceResults,
          closedWorld.commonElements,
          closedWorld,
          log,
        ),
        codeMotion = SsaCodeMotion(closedWorld.abstractValueDomain),
        loadElimination = SsaLoadElimination(closedWorld),
        SsaRedundantPhiEliminator(),
        SsaDeadPhiEliminator(),
        SsaLateFieldOptimizer(closedWorld, log),
        // After GVN and load elimination the same value may be used in code
        // controlled by a test on the value, so redo 'conversion insertion' to
        // learn from the refined type.
        SsaTypeConversionInserter(closedWorld),
        SsaTypePropagator(
          globalInferenceResults,
          closedWorld.commonElements,
          closedWorld,
          log,
        ),
        SsaValueRangeAnalyzer(closedWorld, this, codegen.tracer),
        // Previous optimizations may have generated new
        // opportunities for instruction simplification.
        SsaInstructionSimplifier(
          globalInferenceResults,
          _options,
          closedWorld,
          typeRecipeDomain,
          registry,
          log,
          metrics,
        ),
      ];
      phases.forEach(runPhase);

      // Simplifying interceptors is just an optimization, it is required for
      // implementation correctness because the code generator assumes it is
      // always performed to compute the intercepted classes sets.
      runPhase(SsaSimplifyInterceptors(closedWorld, member.enclosingClass));

      SsaDeadCodeEliminator dce = SsaDeadCodeEliminator(closedWorld, this);
      runPhase(dce);
      if (codeMotion.movedCode ||
          dce.eliminatedSideEffects ||
          dce.newGvnCandidates ||
          loadElimination.newGvnCandidates) {
        phases = [
          SsaTypePropagator(
            globalInferenceResults,
            closedWorld.commonElements,
            closedWorld,
            log,
          ),
          SsaGlobalValueNumberer(closedWorld.abstractValueDomain),
          SsaCodeMotion(closedWorld.abstractValueDomain),
          SsaValueRangeAnalyzer(closedWorld, this, codegen.tracer),
          SsaInstructionSimplifier(
            globalInferenceResults,
            _options,
            closedWorld,
            typeRecipeDomain,
            registry,
            log,
            metrics,
          ),
          SsaSimplifyInterceptors(closedWorld, member.enclosingClass),
          SsaDeadCodeEliminator(closedWorld, this),
        ];
      } else {
        phases = [
          SsaTypePropagator(
            globalInferenceResults,
            closedWorld.commonElements,
            closedWorld,
            log,
          ),
          // Run the simplifier to remove unneeded type checks inserted by
          // type propagation.
          SsaInstructionSimplifier(
            globalInferenceResults,
            _options,
            closedWorld,
            typeRecipeDomain,
            registry,
            log,
            metrics,
          ),
        ];
      }
      phases.forEach(runPhase);
    });

    // SsaFinalizeInterceptors must always be run to ensure consistent calling
    // conventions between SSA-generated code and other code fragments generated
    // by the emitter.
    // TODO(sra): Generate these other fragments via SSA, then this phase
    // becomes an opt-in optimization.
    runPhase(SsaFinalizeInterceptors(closedWorld));
  }
}

/// Returns `true` if [mask] represents only types that have a length that
/// cannot change.  The current implementation is conservative for the purpose
/// of identifying gvn-able lengths and mis-identifies some unions of fixed
/// length indexables (see TODO) as not fixed length.
bool isFixedLength(AbstractValue mask, JClosedWorld closedWorld) {
  AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
  if (abstractValueDomain.isContainer(mask) &&
      abstractValueDomain.getContainerLength(mask) != null) {
    // A container on which we have inferred the length.
    return true;
  }
  // TODO(sra): Recognize any combination of fixed length indexables.
  if (abstractValueDomain.isGrowableArray(mask).isDefinitelyFalse ||
      abstractValueDomain.isStringOrNull(mask).isDefinitelyTrue ||
      abstractValueDomain.isTypedArray(mask).isDefinitelyTrue) {
    return true;
  }
  return false;
}

/// Returns `true` if the end of [block] is unreachable, e.g. due to a `throw`
/// expression.
bool hasUnreachableExit(HBasicBlock block) {
  if (!block.isLive) return false;
  final last = block.last;
  if (last is HGoto) {
    final previous = last.previous;
    if (previous is HThrowExpression) return true;
    // TODO(sra): Match other signs of unreachability, e.g. a call to a method
    // that returns `[empty]`.
  }
  return false;
}

/// If both inputs to known operations are available execute the operation at
/// compile-time.
class SsaInstructionSimplifier extends HBaseVisitor<HInstruction>
    implements OptimizationPhase {
  // We don't produce constant-folded strings longer than this unless they have
  // a single use.  This protects against exponentially large constant folded
  // strings.
  static const maxSharedConstantFoldedStringLength = 512;

  @override
  final String name = "SsaInstructionSimplifier";
  final GlobalTypeInferenceResults _globalInferenceResults;
  final CompilerOptions _options;
  final JClosedWorld _closedWorld;
  final TypeRecipeDomain _typeRecipeDomain;
  final CodegenRegistry _registry;
  final OptimizationTestLog? _log;
  final SsaMetrics _metrics;

  /// Most simplifications become enabled when the types are refined by type
  /// propagation. Some simplifications remove code that helps type progagation
  /// produce a better result. These simplifications are inhibited when
  /// [beforeTypePropagation] is `true` to ensure they are seeing the propagated
  /// types.
  final bool beforeTypePropagation;
  late final HGraph _graph;

  SsaInstructionSimplifier(
    this._globalInferenceResults,
    this._options,
    this._closedWorld,
    this._typeRecipeDomain,
    this._registry,
    this._log,
    this._metrics, {
    this.beforeTypePropagation = false,
  });

  JCommonElements get commonElements => _closedWorld.commonElements;

  AbstractValueDomain get _abstractValueDomain =>
      _closedWorld.abstractValueDomain;

  NativeData get _nativeData => _closedWorld.nativeData;

  @override
  void visitGraph(HGraph visitee) {
    _graph = visitee;
    visitDominatorTree(visitee);
    finalizeArrayFlagEffects();
  }

  @override
  bool validPostcondition(HGraph graph) => true;

  @override
  void visitBasicBlock(HBasicBlock node) {
    simplifyPhis(node);
    HInstruction? instruction = node.first;
    while (instruction != null) {
      HInstruction? next = instruction.next;
      HInstruction replacement = instruction.accept(this);
      if (replacement != instruction) {
        node.rewrite(instruction, replacement);

        // The intersection of double and int return conflicting, and
        // because of our number implementation for JavaScript, it
        // might be that an operation thought to return double, can be
        // simplified to an int. For example:
        // `2.5 * 10`.
        if (!(replacement
                .isNumberOrNull(_abstractValueDomain)
                .isDefinitelyTrue &&
            instruction
                .isNumberOrNull(_abstractValueDomain)
                .isDefinitelyTrue)) {
          // If we can replace [instruction] with [replacement], then
          // [replacement]'s type can be narrowed.
          AbstractValue newType = _abstractValueDomain.intersection(
            replacement.instructionType,
            instruction.instructionType,
          );
          replacement.instructionType = newType;
        }

        // If the replacement instruction does not know its
        // source element, use the source element of the
        // instruction.
        replacement.sourceElement ??= instruction.sourceElement;
        replacement.sourceInformation ??= instruction.sourceInformation;
        if (!replacement.isInBasicBlock()) {
          // The constant folding can return an instruction that is already
          // part of the graph (like an input), so we only add the replacement
          // if necessary.
          node.addAfter(instruction, replacement);
          // Visit the replacement as the next instruction in case it
          // can also be constant folded away.
          next = replacement;
        }
        _removeInstructionAndPureDeadInputs(instruction);
      }
      instruction = next;
    }
  }

  /// Removes [instruction] and the DAG of pure instructions that are transitive
  /// inputs to [instruction].
  ///
  /// It is worth doing the cleanup of removing the instructions in the
  /// simplifier as it reduces the `usedBy` count, which enables rewrites that
  /// are sensitive to the use count. Such rewrites can occur much earlier with
  /// 'online' usedBy counting.  The cost of visiting all inputs of a rewritten
  /// instruction is regained by avoiding visiting the dead instructions in
  /// subsequent passes.
  void _removeInstructionAndPureDeadInputs(HInstruction instruction) {
    List<HInstruction> worklist = instruction.inputs.toList();
    instruction.block!.remove(instruction);
    for (int i = 0; i < worklist.length; i++) {
      HInstruction next = worklist[i];
      final block = next.block;
      if (block == null) continue; // Already removed.
      if (next.usedBy.isEmpty && next.isPure(_abstractValueDomain)) {
        // Special cases that are removed properly by other phases.
        if (next is HParameterValue) continue;
        if (next is HLocalValue) continue;
        if (next is HConstant) continue;
        if (next is HPhi) continue;
        worklist.addAll(next.inputs);
        block.remove(next);
      }
    }
  }

  // Simplify some CFG diamonds to equivalent expressions.
  void simplifyPhis(HBasicBlock block) {
    // Do 'statement' simplifications first, as they might reduce the number of
    // phis to one, enabling an 'expression' simplification.
    var phi = block.phis.firstPhi;
    while (phi != null) {
      final next = phi.nextPhi;
      simplifyStatementPhi(block, phi);
      phi = next;
    }

    if (block.predecessors.length != 2) return;
    phi = block.phis.firstPhi;
    if (phi != null && phi.next == null) {
      simplifyExpressionPhi(block, phi);
    }
  }

  /// Simplify a single phi when there are possibly other phis (i.e. the result
  /// might not be an expression).
  void simplifyStatementPhi(HBasicBlock block, HPhi phi) {
    if (simplifyStatementPhiToCommonInput(block, phi)) return;

    if (block.predecessors.length != 2) return;

    HBasicBlock dominator = block.dominator!;

    // Extract the controlling condition.
    final controlFlow = dominator.last;
    if (controlFlow is! HIf) return;
    HInstruction condition = controlFlow.inputs.single;

    if (condition.isBoolean(_abstractValueDomain).isPotentiallyFalse) return;

    // For the condition to be 'controlling', there must be no way to reach the
    // 'else' join from the 'then' branch and vice versa.
    if (!dominator.successors[0].dominates(block.predecessors[0])) return;
    if (!dominator.successors[1].dominates(block.predecessors[1])) return;

    //  condition ? true : false  -->  condition
    //  condition ? condition : false  -->  condition
    //  condition ? true : condition  -->  condition
    final left = phi.inputs[0];
    final right = phi.inputs[1];
    if ((_isBoolConstant(left, true) || left == condition) &&
        (_isBoolConstant(right, false) || right == condition)) {
      block.rewrite(phi, condition);
      block.removePhi(phi);
      condition.sourceElement ??= phi.sourceElement;
      return;
    }

    //  condition ? false : true  -->  !condition
    if (_isBoolConstant(left, false) && _isBoolConstant(right, true)) {
      HInstruction replacement = HNot(condition, _abstractValueDomain.boolType)
        ..sourceElement = phi.sourceElement
        ..sourceInformation = phi.sourceInformation;
      block.addAtEntry(replacement);
      block.rewrite(phi, replacement);
      block.removePhi(phi);
      return;
    }
  }

  bool simplifyStatementPhiToCommonInput(HBasicBlock block, HPhi phi) {
    // Replace phis that produce the same value on all arms.  The test(s) for
    // control flow often results in a refinement instruction (HTypeKnown), so
    // we recognize that, allowing, e.g.,
    //
    //     condition ? HTypeKnown(x) : x  -->  x
    //     condition ? x : HTypeKnown(x)  -->  x
    //
    // We don't remove loop phis here. SsaRedundantPhiEliminator will eliminate
    // redundant phis without HTypeKnown refinements, including loop phis.

    // There may be control flow that exits early, leaving refinements that
    // cause the type of the phi to be stronger than the source. Don't attempt
    // this simplification until the type of the phi is calculated.
    if (beforeTypePropagation) return false;

    HBasicBlock dominator = block.dominator!;

    /// Find the input, skipping refinements that do not dominate the condition,
    /// e.g., skipping refinements in the arm of the if-then-else.
    HInstruction? dominatingRefinementInput(HInstruction input) {
      while (true) {
        if (input.block!.dominates(dominator)) return input;
        if (input is! HTypeKnown) return null;
        input = input.checkedInput;
      }
    }

    final commonInput = dominatingRefinementInput(phi.inputs.first);
    if (commonInput == null) return false;

    for (int i = 1; i < phi.inputs.length; i++) {
      final next = dominatingRefinementInput(phi.inputs[i]);
      if (!identical(next, commonInput)) return false;
    }

    HTypeKnown replacement = HTypeKnown.pinned(
      phi.instructionType,
      commonInput,
    );
    block.addBefore(block.first, replacement);
    block.rewrite(phi, replacement);
    block.removePhi(phi);
    return true;
  }

  /// Simplify some CFG diamonds to equivalent expressions.
  void simplifyExpressionPhi(HBasicBlock block, HPhi phi) {
    // Is [block] the join point for a simple diamond?
    assert(phi.inputs.length == 2);
    HBasicBlock b1 = block.predecessors[0];
    HBasicBlock b2 = block.predecessors[1];
    HBasicBlock dominator = block.dominator!;
    if (!(b1.dominator == dominator && b2.dominator == dominator)) return;

    // Extract the controlling condition.
    final controlFlow = dominator.last;
    if (controlFlow is! HIf) return;
    HInstruction test = controlFlow.inputs.single;

    if (test.usedBy.length > 1) return;

    bool negated = false;
    while (test is HNot) {
      test = test.inputs.single;
      if (test.usedBy.length > 1) return;
      negated = !negated;
    }

    if (test is! HIdentity) return;
    HInstruction tested;
    if (test.inputs[0].isNull(_abstractValueDomain).isDefinitelyTrue) {
      tested = test.inputs[1];
    } else if (test.inputs[1].isNull(_abstractValueDomain).isDefinitelyTrue) {
      tested = test.inputs[0];
    } else {
      return;
    }

    HInstruction whenNullValue = phi.inputs[negated ? 1 : 0];
    HInstruction whenNotNullValue = phi.inputs[negated ? 0 : 1];
    HBasicBlock whenNullBlock = block.predecessors[negated ? 1 : 0];
    HBasicBlock whenNotNullBlock = block.predecessors[negated ? 0 : 1];

    // If 'x' is nullable boolean,
    //
    //     x == null ? false : x  --->  x == true
    //
    // This ofen comes from the dart code `x ?? false`.
    if (_sameOrRefinementOf(tested, whenNotNullValue) &&
        _isBoolConstant(whenNullValue, false) &&
        whenNotNullValue
            .isBooleanOrNull(_abstractValueDomain)
            .isDefinitelyTrue &&
        _mostlyEmpty(whenNullBlock) &&
        _mostlyEmpty(whenNotNullBlock)) {
      HInstruction trueConstant = _graph.addConstantBool(true, _closedWorld);
      HInstruction replacement =
          HIdentity(tested, trueConstant, _abstractValueDomain.boolType)
            ..sourceElement = phi.sourceElement
            ..sourceInformation = phi.sourceInformation;
      block.rewrite(phi, replacement);
      block.addAtEntry(replacement);
      block.removePhi(phi);
      return;
    }
    // If 'x' is nullable boolean,
    //
    //     x == null ? true : x  --->  !(x == false)
    //
    // This ofen comes from the dart code `x ?? true`.
    if (_sameOrRefinementOf(tested, whenNotNullValue) &&
        _isBoolConstant(whenNullValue, true) &&
        whenNotNullValue
            .isBooleanOrNull(_abstractValueDomain)
            .isDefinitelyTrue &&
        _mostlyEmpty(whenNullBlock) &&
        _mostlyEmpty(whenNotNullBlock)) {
      HInstruction falseConstant = _graph.addConstantBool(false, _closedWorld);
      HInstruction compare = HIdentity(
        tested,
        falseConstant,
        _abstractValueDomain.boolType,
      );
      block.addAtEntry(compare);
      HInstruction replacement = HNot(compare, _abstractValueDomain.boolType)
        ..sourceElement = phi.sourceElement
        ..sourceInformation = phi.sourceInformation;
      block.rewrite(phi, replacement);
      block.addAfter(compare, replacement);
      block.removePhi(phi);
      return;
    }

    // TODO(sra): Consider other simple diamonds, e.g. with the addition of a
    // special instruction,
    //
    //     s == null ? "" : s  --->  s || "".
    return;
  }

  bool _isBoolConstant(HInstruction node, bool value) {
    if (node is HConstant) {
      ConstantValue c = node.constant;
      if (c is BoolConstantValue) {
        return c.boolValue == value;
      }
    }
    return false;
  }

  bool _sameOrRefinementOf(HInstruction base, HInstruction insn) {
    if (base == insn) return true;
    if (insn is HTypeKnown) return _sameOrRefinementOf(base, insn.checkedInput);
    return false;
  }

  bool _mostlyEmpty(HBasicBlock block) {
    for (HInstruction? insn = block.first; insn != null; insn = insn.next) {
      if (insn is HTypeKnown) continue;
      if (insn is HGoto) return true;
      return false;
    }
    return true;
  }

  @override
  HInstruction visitInstruction(HInstruction instruction) {
    return instruction;
  }

  ConstantValue? getConstantFromType(HInstruction node) {
    if (node.isValue(_abstractValueDomain) &&
        node.isNull(_abstractValueDomain).isDefinitelyFalse &&
        node.isLateSentinel(_abstractValueDomain).isDefinitelyFalse) {
      final value = _abstractValueDomain.getPrimitiveValue(
        node.instructionType,
      );
      if (value is BoolConstantValue) {
        return value;
      }
      // TODO(het): consider supporting other values (short strings?)
    }
    return null;
  }

  void propagateConstantValueToUses(HInstruction node) {
    if (node.usedBy.isEmpty) return;
    final value = getConstantFromType(node);
    if (value != null) {
      HConstant constant = _graph.addConstant(value, _closedWorld);
      for (HInstruction user in node.usedBy.toList()) {
        user.changeUse(node, constant);
      }
    }
  }

  @override
  HInstruction visitParameterValue(HParameterValue node) {
    // [HParameterValue]s are either the value of the parameter (in fully SSA
    // converted code), or the mutable variable containing the value (in
    // incompletely SSA converted code, e.g. methods containing exceptions).
    //
    // If the parameter is used as a mutable variable we cannot replace the
    // variable with a value.
    //
    // If the parameter is used as a mutable variable but never written, first
    // convert to a value parameter.

    if (node.usedAsVariable()) {
      // Trivial SSA-conversion. Replace all HLocalGet instructions with the
      // parameter.
      //
      // If there is a single assignment, it could dominate all the reads, or
      // dominate all the reads except one read, which was used to 'check' the
      // value at entry, like this:
      //
      //     t1 = HLocalGet(param);
      //     t2 = check(t1);           // replace t1 with param
      //     HLocalSet(param, t2);
      //     ....
      //     t3 = HLocalGet(param);
      //     ... t3 ...                // replace t3 with t2
      //
      HLocalSet? assignment;
      for (HInstruction user in node.usedBy) {
        if (user is HLocalSet) {
          assert(user.local == node);
          if (assignment != null) return node; // Two or more assignments.
          assignment = user;
          continue;
        }
        if (user is HLocalGet) continue;
        // There should not really be anything else but there are Phis which
        // have not been cleaned up.
        return node;
      }
      HLocalGet? checkedLoad;
      HInstruction value = node;
      if (assignment != null) {
        value = assignment.value;
        HInstruction source = value.nonCheck();
        if (source is HLocalGet && source.local == node) {
          if (source.usedBy.length != 1) return node;
          checkedLoad = source;
        }
      }
      // If there is a single assignment it will dominate all other uses.
      List<HLocalGet> loads = [];
      for (HInstruction user in node.usedBy) {
        if (user == assignment) continue;
        if (user == checkedLoad) continue;
        assert(user is HLocalGet && user.local == node);
        if (assignment != null && !assignment.dominates(user)) return node;
        loads.add(user as HLocalGet);
      }

      for (HLocalGet user in loads) {
        final block = user.block!;
        block.rewrite(user, value);
        block.remove(user);
      }
      if (checkedLoad != null) {
        final block = checkedLoad.block!;
        block.rewrite(checkedLoad, node);
        block.remove(checkedLoad);
      }
      if (assignment != null) {
        assignment.block!.remove(assignment);
      }
    }

    propagateConstantValueToUses(node);
    return node;
  }

  @override
  HInstruction visitNot(HNot node) {
    List<HInstruction> inputs = node.inputs;
    assert(inputs.length == 1);
    HInstruction input = inputs[0];
    if (input is HConstant) {
      return _graph.addConstantBool(
        input.constant is! TrueConstantValue,
        _closedWorld,
      );
    } else if (input is HNot) {
      return input.inputs[0];
    }
    return node;
  }

  @override
  HInstruction visitInvokeUnary(HInvokeUnary node) {
    final folded = foldUnary(node.operation(), node.operand);
    return folded ?? node;
  }

  HInstruction? foldUnary(
    constant_system.UnaryOperation operation,
    HInstruction operand,
  ) {
    if (operand is HConstant) {
      HConstant receiver = operand;
      final folded = operation.fold(receiver.constant);
      if (folded != null) return _graph.addConstant(folded, _closedWorld);
    }
    return null;
  }

  HInstruction? tryOptimizeLengthInterceptedGetter(HInvokeDynamic node) {
    HInstruction actualReceiver = node.inputs[1];

    if (actualReceiver is HConstant) {
      ConstantValue constant = actualReceiver.constant;
      if (constant is StringConstantValue) {
        return _graph.addConstantInt(constant.length, _closedWorld);
      }
      if (constant is ListConstantValue) {
        return _graph.addConstantInt(constant.length, _closedWorld);
      }
      if (constant is MapConstantValue) {
        return _graph.addConstantInt(constant.length, _closedWorld);
      }
    }

    if (actualReceiver
        .isIndexablePrimitive(_abstractValueDomain)
        .isDefinitelyTrue) {
      bool isFixed = isFixedLength(
        actualReceiver.instructionType,
        _closedWorld,
      );
      AbstractValue actualType = node.instructionType;
      AbstractValue resultType = _abstractValueDomain.positiveIntType;
      // If we already have computed a more specific type, keep that type.
      if (_abstractValueDomain
          .isInstanceOf(actualType, commonElements.jsUInt31Class)
          .isDefinitelyTrue) {
        resultType = _abstractValueDomain.uint31Type;
      } else if (_abstractValueDomain
          .isInstanceOf(actualType, commonElements.jsUInt32Class)
          .isDefinitelyTrue) {
        resultType = _abstractValueDomain.uint32Type;
      }
      HInstruction checkedReceiver = actualReceiver;
      if (actualReceiver.isNull(_abstractValueDomain).isPotentiallyTrue) {
        // The receiver is potentially `null` so we insert a null receiver
        // check. This will be folded into the length access later.
        HNullCheck check =
            HNullCheck(
                actualReceiver,
                _abstractValueDomain.excludeNull(
                  actualReceiver.instructionType,
                ),
              )
              ..selector = node.selector
              ..sourceInformation = node.sourceInformation;
        _log?.registerNullCheck(node, check);
        node.block!.addBefore(node, check);
        checkedReceiver = check;
      }
      HGetLength result = HGetLength(
        checkedReceiver,
        resultType,
        isAssignable: !isFixed,
      );
      return result;
    }
    return null;
  }

  HInstruction handleInterceptedCall(HInvokeDynamic node) {
    // Try constant folding the instruction.
    final operation = node.specializer.operation();
    if (operation != null) {
      HInstruction? folded;
      if (operation is constant_system.UnaryOperation) {
        assert(node.inputs.length == 2);
        folded = foldUnary(operation, node.inputs[1]);
      } else if (operation is constant_system.BinaryOperation) {
        assert(node.inputs.length == 3);
        folded = foldBinary(operation, node.inputs[1], node.inputs[2]);
      }
      if (folded != null) {
        _metrics.countOperationFolded.add();
        return folded;
      }
    }

    // Try converting the instruction to a builtin instruction.
    final instruction = node.specializer.tryConvertToBuiltin(
      node,
      _graph,
      _globalInferenceResults,
      commonElements,
      _closedWorld,
      _log,
    );
    if (instruction != null) {
      _metrics.countSpecializations.add();
      return instruction;
    }

    Selector selector = node.selector;
    AbstractValue mask = node.receiverType;
    HInstruction input = node.inputs[1];

    bool applies(MemberEntity element) {
      return selector.applies(element) &&
          _abstractValueDomain
              .isTargetingMember(mask, element, selector.memberName)
              .isPotentiallyTrue;
    }

    if (selector.isCall || selector.isOperator) {
      FunctionEntity? target;
      if (input.isGrowableArray(_abstractValueDomain).isDefinitelyTrue) {
        if (applies(commonElements.jsArrayAdd)) {
          // Codegen special cases array calls to `Array.push`, but does not
          // inline argument type checks. We lower if the check always passes
          // (due to invariance or being a top-type), or if the check is not
          // emitted.
          if (node.isInvariant ||
              input is HLiteralList ||
              !_closedWorld.annotationsData
                  .getParameterCheckPolicy(commonElements.jsArrayAdd)
                  .isEmitted) {
            target = commonElements.jsArrayAdd;
          }
        }
      } else if (input.isStringOrNull(_abstractValueDomain).isDefinitelyTrue) {
        if (commonElements.appliesToJsStringSplit(
          selector,
          mask,
          _abstractValueDomain,
        )) {
          return handleStringSplit(node);
        } else if (applies(commonElements.jsStringOperatorAdd)) {
          // `operator+` is turned into a JavaScript '+' so we need to
          // make sure the receiver and the argument are not null.
          // TODO(sra): Do this via [node.specializer].
          HInstruction argument = node.inputs[2];
          if (argument.isString(_abstractValueDomain).isDefinitelyTrue &&
              input.isNull(_abstractValueDomain).isDefinitelyFalse) {
            return HStringConcat(input, argument, node.instructionType);
          }
        } else if (applies(commonElements.jsStringToString) &&
            input.isNull(_abstractValueDomain).isDefinitelyFalse) {
          return input;
        }
      }
      if (target != null) {
        // TODO(ngeoffray): There is a strong dependency between codegen
        // and this optimization that the dynamic invoke does not need an
        // interceptor. We currently need to keep a
        // HInvokeDynamicMethod and not create a HForeign because
        // HForeign is too opaque for the SsaCheckInserter (that adds a
        // bounds check on removeLast). Once we start inlining, the
        // bounds check will become explicit, so we won't need this
        // optimization.
        // TODO(sra): Fix comment - SsaCheckInserter is deleted.
        HInvokeDynamicMethod result = HInvokeDynamicMethod(
          node.selector,
          node.receiverType,
          node.inputs.sublist(1), // Drop interceptor.
          node.instructionType,
          node.typeArguments,
          node.sourceInformation,
          isIntercepted: false,
        );
        result.element = target;
        return result;
      }
    } else if (selector.isGetter) {
      if (commonElements.appliesToJsIndexableLength(selector)) {
        final optimized = tryOptimizeLengthInterceptedGetter(node);
        if (optimized != null) {
          _metrics.countLengthOptimized.add();
          return optimized;
        }
      }
    }

    return node;
  }

  HInstruction handleStringSplit(HInvokeDynamic node) {
    HInstruction argument = node.inputs[2];
    if (!argument.isString(_abstractValueDomain).isDefinitelyTrue) {
      return node;
    }

    // Replace `s.split$1(pattern)` with
    //
    //     t1 = s.split(pattern);
    //     t2 = String;
    //     t3 = JSArray<t2>;
    //     t4 = setArrayType(t1, t3);
    //

    AbstractValue resultMask = _abstractValueDomain.growableListType;

    HInvokeDynamicMethod splitInstruction =
        HInvokeDynamicMethod(
            node.selector,
            node.receiverType,
            node.inputs.sublist(1), // Drop interceptor.
            resultMask,
            const <DartType>[],
            node.sourceInformation,
            isIntercepted: false,
          )
          ..element = commonElements.jsStringSplit
          ..setAllocation(true);

    if (!_closedWorld.rtiNeed.classNeedsTypeArguments(
      commonElements.jsArrayClass,
    )) {
      return splitInstruction;
    }

    node.block!.addBefore(node, splitInstruction);

    HInstruction typeInfo = HLoadType.type(
      _closedWorld.elementEnvironment.createInterfaceType(
        commonElements.jsArrayClass,
        [commonElements.stringType],
      ),
      _abstractValueDomain.dynamicType,
    );
    node.block!.addBefore(node, typeInfo);

    HInvokeStatic tagInstruction = HInvokeStatic(
      commonElements.setArrayType,
      [splitInstruction, typeInfo],
      resultMask,
      const <DartType>[],
    );
    // 'Linear typing' trick: [tagInstruction] is the only use of the
    // [splitInstruction], so it becomes the sole alias.
    // TODO(sra): Build this knowledge into alias analysis.
    tagInstruction.setAllocation(true);

    return tagInstruction;
  }

  @override
  HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
    propagateConstantValueToUses(node);
    if (node.isInterceptedCall) {
      HInstruction folded = handleInterceptedCall(node);
      if (folded != node) return folded;
    }

    HInstruction receiver = node.getDartReceiver(_closedWorld);
    AbstractValue receiverType = receiver.instructionType;
    final element = _closedWorld.locateSingleMember(
      node.selector,
      receiverType,
    );
    if (element == null) return node;

    // TODO(ngeoffray): Also fold if it's a getter or variable.
    if (element.isFunction &&
        // If we found out that the only target is an implicitly called
        // `noSuchMethod` we just ignore it.
        node.selector.applies(element)) {
      // `.isFunction` implies FunctionEntity, but not vice-versa.
      FunctionEntity method = element as FunctionEntity;

      if (_nativeData.isNativeMember(method)) {
        return tryInlineNativeMethod(node, method) ?? node;
      }

      // TODO(ngeoffray): If the method has optional parameters, we should pass
      // the default values.
      ParameterStructure parameters = method.parameterStructure;
      if (parameters.totalParameters == node.selector.argumentCount &&
          parameters.typeParameters ==
              node.selector.callStructure.typeArgumentCount) {
        node.element = method;
      }
      return node;
    }

    // Replace method calls through fields with a closure call on the value of
    // the field. This usually removes the demand for the call-through stub and
    // makes the field load available to further optimization, e.g. LICM.

    if (element is FieldEntity && element.name == node.selector.name) {
      FieldEntity field = element;
      if (!_nativeData.isNativeMember(field) &&
          !node.isCallOnInterceptor(_closedWorld)) {
        // Insertion point for the closure call.
        HInstruction insertionPoint = node;
        HInstruction load;
        FieldAnalysisData fieldData = _closedWorld.fieldAnalysis.getFieldData(
          field,
        );
        if (fieldData.isEffectivelyConstant) {
          // The field is elided and replace it with its constant value.
          if (_abstractValueDomain.isNull(receiverType).isPotentiallyTrue) {
            // The receiver is potentially `null` so we insert a null receiver
            // check to trigger a null pointer exception.  Insert check
            // conditionally to avoid the work of removing it later.
            HNullCheck check =
                HNullCheck(
                    receiver,
                    _abstractValueDomain.excludeNull(receiverType),
                  )
                  ..selector = node.selector
                  ..sourceInformation = node.sourceInformation;
            _log?.registerNullCheck(node, check);
            node.block!.addBefore(node, check);
            insertionPoint = check;
          }
          HConstant constant = _graph.addConstant(
            fieldData.constantValue!,
            _closedWorld,
            sourceInformation: node.sourceInformation,
          );
          _log?.registerConstantFieldCall(node, field, constant);
          load = constant;
        } else {
          AbstractValue type = AbstractValueFactory.inferredTypeForMember(
            field,
            _globalInferenceResults,
          );
          HFieldGet fieldGet = HFieldGet(
            field,
            receiver,
            type,
            node.sourceInformation,
            isAssignable: field.isAssignable,
          );
          _log?.registerFieldCall(node, fieldGet);
          node.block!.addBefore(node, fieldGet);
          insertionPoint = fieldGet;
          load = fieldGet;
        }
        Selector callSelector = Selector.callClosureFrom(node.selector);
        List<HInstruction> inputs = [
          load,
          ...node.inputs.skip(node.isInterceptedCall ? 2 : 1),
        ];
        DartType fieldType = _closedWorld.elementEnvironment.getFieldType(
          field,
        );
        HInstruction closureCall = HInvokeClosure(
          callSelector,
          _abstractValueDomain.createFromStaticType(fieldType).abstractValue,
          inputs,
          node.instructionType,
          node.typeArguments,
        )..sourceInformation = node.sourceInformation;
        node.block!.addAfter(insertionPoint, closureCall);
        return closureCall;
      }
    }

    return node;
  }

  bool _avoidInliningNativeMethod(HInvokeDynamic node, FunctionEntity method) {
    assert(_nativeData.isNativeMember(method));
    if (_options.disableInlining) return true;
    if (_closedWorld.annotationsData.hasNoInline(method)) {
      return true;
    }
    return false;
  }

  // Try to 'inline' an instance getter call to a known native or js-interop
  // getter. This replaces the call to the getter on the Dart interceptor with a
  // direct call to the external method.
  HInstruction? tryInlineNativeGetter(
    HInvokeDynamicGetter node,
    FunctionEntity method,
  ) {
    if (_avoidInliningNativeMethod(node, method)) return null;

    // Strengthen instruction type from annotations to help optimize dependent
    // instructions.
    NativeBehavior nativeBehavior = _nativeData.getNativeMethodBehavior(method);
    AbstractValue returnType = AbstractValueFactory.fromNativeBehavior(
      nativeBehavior,
      _closedWorld,
    );
    HInstruction receiver = node.inputs.last; // Drop interceptor.
    receiver = maybeGuardWithNullCheck(receiver, node, null);
    final result = HInvokeExternal(
      method,
      [receiver],
      returnType,
      nativeBehavior,
      sourceInformation: node.sourceInformation,
    );
    _registry.registerStaticUse(StaticUse.methodInlining(method, null));
    // Assume Native getters effect-free as an approximation to being
    // idempotent.
    // TODO(sra): [native.BehaviorBuilder.buildMethodBehavior] should do this
    // for us.
    result.sideEffects.setDependsOnSomething();
    result.sideEffects.clearAllSideEffects();
    result.setUseGvn();

    return maybeAddNativeReturnNullCheck(node, result, method);
  }

  HInstruction maybeAddNativeReturnNullCheck(
    HInstruction node,
    HInvokeExternal invocation,
    FunctionEntity method,
  ) {
    HInstruction replacement = invocation;
    if (_options.nativeNullAssertions && memberEntityIsInWebLibrary(method)) {
      FunctionType type = _closedWorld.elementEnvironment.getFunctionType(
        method,
      );
      if (_closedWorld.dartTypes.isNonNullable(type.returnType)) {
        node.block!.addBefore(node, invocation);
        replacement = HNullCheck(
          invocation,
          _abstractValueDomain.excludeNull(invocation.instructionType),
          sticky: true,
        );
      }
    } else if (_options.interopNullAssertions) {
      final name = PublicName(
        _nativeData.computeUnescapedJSInteropName(method.name!),
      );
      final selector = method.isGetter
          ? Selector.getter(name)
          : Selector.call(
              name,
              CallStructure.unnamed(invocation.inputs.length),
            );
      if (_nativeData.interopNullChecks.containsKey(selector)) {
        FunctionType type = _closedWorld.elementEnvironment.getFunctionType(
          method,
        );
        if (_closedWorld.dartTypes.isNonNullable(type.returnType)) {
          node.block!.addBefore(node, invocation);
          replacement = HInvokeStatic(
            commonElements.interopNullAssertion,
            [invocation],
            _abstractValueDomain.excludeNull(invocation.instructionType),
            const <DartType>[],
          );
        }
      }
    }
    return replacement;
  }

  // Try to 'inline' an instance setter call to a known native or js-interop
  // getter. This replaces the call to the setter on the Dart interceptor with a
  // direct call to the external method.
  HInstruction? tryInlineNativeSetter(
    HInvokeDynamicSetter node,
    FunctionEntity method,
  ) {
    if (_avoidInliningNativeMethod(node, method)) return null;

    assert(node.inputs.length == 3);
    HInstruction receiver = node.inputs[1];
    HInstruction value = node.inputs[2];
    FunctionType type = _closedWorld.elementEnvironment.getFunctionType(method);
    assert(type.optionalParameterTypes.isEmpty);
    assert(type.namedParameterTypes.isEmpty);
    DartType parameterType = type.parameterTypes.single;
    if (_nativeArgumentNeedsCheckOrConversion(method, parameterType, value)) {
      return null;
    }

    NativeBehavior nativeBehavior = _nativeData.getNativeMethodBehavior(method);
    receiver = maybeGuardWithNullCheck(receiver, node, null);
    HInvokeExternal result = HInvokeExternal(
      method,
      [receiver, value],
      value.instructionType,
      nativeBehavior,
      sourceInformation: node.sourceInformation,
    );
    _registry.registerStaticUse(StaticUse.methodInlining(method, null));
    return result;
  }

  // TODO(sra): Refactor this code so that we can decide to inline the method
  // with a few checks or conversions. We would want to do this if there was a
  // single call site to [method], or most arguments do not require a check.
  bool _nativeArgumentNeedsCheckOrConversion(
    FunctionEntity method,
    DartType parameterType,
    HInstruction argument,
  ) {
    // TODO(sra): JS-interop *instance* methods don't check their arguments
    // since the forwarding stub is shared by all JS-interop methods with the
    // same name, regardless of parameter types. We could 'inline' js-interop
    // calls even when the types of the arguments are incorrect.

    if (!_nativeData.isJsInteropMember(method)) {
      // @Native methods have conversion code for function arguments. Rather
      // than insert that code at the inlined call site, call the target on the
      // interceptor.
      if (parameterType.withoutNullability is FunctionType) return true;
    }

    if (!_closedWorld.annotationsData
        .getParameterCheckPolicy(method)
        .isEmitted) {
      // If the target has no checks we can inline.
      return false;
    }

    final parameterAbstractValue = _abstractValueDomain
        .getAbstractValueForNativeMethodParameterType(parameterType);

    if (parameterAbstractValue == null ||
        _abstractValueDomain
            .isIn(argument.instructionType, parameterAbstractValue)
            .isPotentiallyFalse) {
      return true;
    }
    return false;
  }

  // Try to 'inline' an instance method call to a known native or js-interop
  // method. This replaces the call to the method on the Dart interceptor with a
  // direct call to the external method.
  HInstruction? tryInlineNativeMethod(
    HInvokeDynamicMethod node,
    FunctionEntity method,
  ) {
    if (_avoidInliningNativeMethod(node, method)) return null;
    // We can replace the call to the native class interceptor method (target)
    // if the target does no conversions or useful type checks.

    FunctionType type = _closedWorld.elementEnvironment.getFunctionType(method);
    if (type.namedParameters.isNotEmpty) return null;

    // The call site might omit optional arguments. The inlined code must
    // preserve the number of arguments, so check only the actual arguments.
    bool canInline = true;
    List<HInstruction> inputs = node.inputs;
    int inputPosition = 2; // Skip interceptor and receiver.

    void checkParameterType(DartType parameterType) {
      if (!canInline) return;
      if (inputPosition >= inputs.length) return;
      HInstruction input = inputs[inputPosition++];
      if (_nativeArgumentNeedsCheckOrConversion(method, parameterType, input)) {
        canInline = false;
      }
    }

    type.parameterTypes.forEach(checkParameterType);
    type.optionalParameterTypes.forEach(checkParameterType);
    assert(type.namedParameterTypes.isEmpty);

    if (!canInline) return null;

    // Strengthen instruction type from annotations to help optimize
    // dependent instructions.
    NativeBehavior nativeBehavior = _nativeData.getNativeMethodBehavior(method);
    AbstractValue returnType = AbstractValueFactory.fromNativeBehavior(
      nativeBehavior,
      _closedWorld,
    );
    HInstruction receiver = inputs[1];
    receiver = maybeGuardWithNullCheck(receiver, node, null);
    final result = HInvokeExternal(
      method,
      [receiver, ...inputs.skip(2)], // '2': Drop interceptor and receiver.
      returnType,
      nativeBehavior,
      sourceInformation: node.sourceInformation,
    );
    _registry.registerStaticUse(StaticUse.methodInlining(method, null));

    return maybeAddNativeReturnNullCheck(node, result, method);
  }

  HConstant? foldBinary(
    constant_system.BinaryOperation operation,
    HInstruction left,
    HInstruction right,
  ) {
    if (left is HConstant && right is HConstant) {
      ConstantValue? folded = operation.fold(left.constant, right.constant);
      if (folded != null) return _graph.addConstant(folded, _closedWorld);
    }
    return null;
  }

  @override
  HInstruction visitAdd(HAdd node) {
    HInstruction left = node.left;
    HInstruction right = node.right;
    // We can only perform this rewriting on Integer, as it is not
    // valid for -0.0.
    if (left.isInteger(_abstractValueDomain).isDefinitelyTrue &&
        right.isInteger(_abstractValueDomain).isDefinitelyTrue) {
      if (left is HConstant && left.constant.isZero) return right;
      if (right is HConstant && right.constant.isZero) return left;
    }
    return super.visitAdd(node);
  }

  @override
  HInstruction visitSubtract(HSubtract node) {
    HInstruction left = node.left;
    HInstruction right = node.right;
    if (right is HConstant) {
      final constant = right.constant;
      // Rewrite `a - 0` to `a`, provided the zero is not negative zero.
      if (constant.isZero && !constant.isMinusZero) return left;
    }
    return super.visitSubtract(node);
  }

  @override
  HInstruction visitMultiply(HMultiply node) {
    HInstruction left = node.left;
    HInstruction right = node.right;
    if (left.isNumber(_abstractValueDomain).isDefinitelyTrue &&
        right.isNumber(_abstractValueDomain).isDefinitelyTrue) {
      if (left is HConstant && left.constant.isOne) return right;
      if (right is HConstant && right.constant.isOne) return left;
    }
    return super.visitMultiply(node);
  }

  @override
  HInstruction visitInvokeBinary(HInvokeBinary node) {
    HInstruction left = node.left;
    HInstruction right = node.right;
    constant_system.BinaryOperation operation = node.operation();
    final folded = foldBinary(operation, left, right);
    if (folded != null) return folded;
    return node;
  }

  HInstruction? handleIdentityCheck(HRelational node) {
    HInstruction left = node.left;
    HInstruction right = node.right;
    AbstractValue leftType = left.instructionType;
    AbstractValue rightType = right.instructionType;

    HInstruction makeTrue() => _graph.addConstantBool(true, _closedWorld);
    HInstruction makeFalse() => _graph.addConstantBool(false, _closedWorld);

    // Intersection of int and double return conflicting, so
    // we don't optimize on numbers to preserve the runtime semantics.
    // TODO(sra): The above is probably no longer true.
    if (!(left.isNumberOrNull(_abstractValueDomain).isDefinitelyTrue &&
        right.isNumberOrNull(_abstractValueDomain).isDefinitelyTrue)) {
      if (_abstractValueDomain
          .areDisjoint(leftType, rightType)
          .isDefinitelyTrue) {
        return makeFalse();
      }
    }

    if (left.isNull(_abstractValueDomain).isDefinitelyTrue &&
        right.isNull(_abstractValueDomain).isDefinitelyTrue) {
      return makeTrue();
    }

    // `x == true` --> `x`
    // `x == false` --> `!x`
    HInstruction? tryCompareConstant(
      HConstant constantInput,
      HInstruction otherInput,
    ) {
      final constant = constantInput.constant;
      if (constant is BoolConstantValue &&
          otherInput.isBoolean(_abstractValueDomain).isDefinitelyTrue) {
        return constant.boolValue
            ? otherInput
            : HNot(otherInput, _abstractValueDomain.boolType);
      }
      return null;
    }

    HInstruction? replacement;
    if (left is HConstant) {
      replacement = tryCompareConstant(left, right);
    } else if (right is HConstant) {
      replacement = tryCompareConstant(right, left);
    }
    if (replacement != null) return replacement;

    if (identical(left.nonCheck(), right.nonCheck())) {
      // Avoid constant-folding `identical(x, x)` when `x` might be double.  The
      // dart2js runtime has not always been consistent with the Dart
      // specification (section 16.0.1), which makes distinctions on NaNs and
      // -0.0 that are hard to implement efficiently.
      if (left.isIntegerOrNull(_abstractValueDomain).isDefinitelyTrue) {
        return makeTrue();
      }
      if (left.isPrimitiveNumber(_abstractValueDomain).isDefinitelyFalse) {
        return makeTrue();
      }
    }

    return null;
  }

  FieldEntity _indexFieldOfEnumClass(ClassEntity enumClass) {
    // We expect the enum class to extend `_Enum`, which has an `index` field,
    // but that might be shadowed by an abstract getter from the class or a
    // mixin.
    ClassEntity? cls = enumClass;
    MemberEntity? foundMember;
    while (cls != null) {
      final member = _closedWorld.elementEnvironment.lookupClassMember(
        cls,
        const PublicName('index'),
      );
      if (member == null) break; // should never happen.
      foundMember = member;
      if (member is FieldEntity) return member;
      if (!member.isAbstract) break;
      cls = _closedWorld.elementEnvironment.getSuperClass(cls);
    }
    throw StateError('$enumClass should have index field, found $foundMember');
  }

  IntConstantValue _indexValueOfEnumConstant(
    ConstantValue constant,
    ClassEntity enumClass,
    FieldEntity field,
  ) {
    if (constant is ConstructedConstantValue) {
      if (constant.type.element == enumClass) {
        final value = constant.fields[field];
        if (value is IntConstantValue) return value;
      }
    }
    throw StateError(
      'Enum constant ${constant.toStructuredText(_closedWorld.dartTypes)}'
      ' should have $field',
    );
  }

  // The `enum` class of the [node], or `null` if [node] does not have an
  // non-nullable enum type.
  ClassEntity? _enumClass(HInstruction node) {
    final cls = _abstractValueDomain.getExactClass(node.instructionType);
    if (cls == null) return null;
    if (_closedWorld.elementEnvironment.isEnumClass(cls)) return cls;
    return null;
  }

  // Try to replace enum labels in a switch with the index values. This is
  // usually smaller, faster, and might allow the JavaScript engine to compile
  // the switch to a jump-table.
  void _tryReduceEnumsInSwitch(HSwitch node) {
    final enumClass = _enumClass(node.expression);
    if (enumClass == null) return;

    FieldEntity indexField = _indexFieldOfEnumClass(enumClass);
    // In some cases the `index` field is elided. We can't load an elided field.
    //
    // TODO(sra): The ConstantValue has the index value, so we can still reduce
    // the enum to the index value. We could handle an elided `index` field in
    // some cases by doing this optimization more like scalar replacement or
    // unboxing, replacing all enums in the method at once, possibly reducing
    // phis of enums to phis of indexes.
    if (_closedWorld.fieldAnalysis.getFieldData(indexField).isElided) return;

    // All the label expressions should be of the same enum class as the switch
    // expression.
    for (final label in node.inputs.skip(1)) {
      if (label is! HConstant) return;
      if (_enumClass(label) != enumClass) return;
    }

    final loadIndex = _directFieldGet(node.expression, indexField, node);
    node.block!.addBefore(node, loadIndex);
    node.replaceInput(0, loadIndex);

    for (int i = 1; i < node.inputs.length; i++) {
      ConstantValue labelConstant = (node.inputs[i] as HConstant).constant;
      node.replaceInput(
        i,
        _graph.addConstant(
          _indexValueOfEnumConstant(labelConstant, enumClass, indexField),
          _closedWorld,
        ),
      );
    }
  }

  @override
  HInstruction visitSwitch(HSwitch node) {
    _tryReduceEnumsInSwitch(node);
    return node;
  }

  @override
  HInstruction visitIdentity(HIdentity node) {
    final newInstruction = handleIdentityCheck(node);
    return newInstruction ?? super.visitIdentity(node);
  }

  @override
  HInstruction visitIsLateSentinel(HIsLateSentinel node) {
    HInstruction value = node.inputs[0];
    AbstractBool isLateSentinel = value.isLateSentinel(_abstractValueDomain);
    if (isLateSentinel.isDefinitelyTrue) {
      _metrics.countLateSentinelCheckDecided.add();
      return _graph.addConstantBool(true, _closedWorld);
    } else if (isLateSentinel.isDefinitelyFalse) {
      _metrics.countLateSentinelCheckDecided.add();
      return _graph.addConstantBool(false, _closedWorld);
    }

    return super.visitIsLateSentinel(node);
  }

  void simplifyCondition(
    HBasicBlock? block,
    HInstruction condition,
    bool value,
    String tag,
  ) {
    if (block == null) return;

    // `excludePhiOutEdges: true` prevents replacing a partially dominated phi
    // node input with a constant. This tends to add unnecessary assignments, by
    // transforming the following, which has phi(false, x),
    //
    //    if (x) { init(); x = false; }
    //
    // into this, which has phi(false, false)
    //
    //    if (x) { init(); x = false; } else { x = false; }
    //
    // which is further simplified to:
    //
    //    if (x) { init(); }
    //    ...
    //    x = false;
    //
    // This is mostly harmless (if a little confusing) but does cause a lot of
    // `x = false;` copies to be inserted when a loop body has many continue
    // statements or ends with a switch.
    DominatedUses uses = DominatedUses.of(
      condition,
      block.first!,
      excludePhiOutEdges: true,
    );
    if (uses.isEmpty) return;
    uses.replaceWith(_graph.addConstantBool(value, _closedWorld));
    _log?.registerConditionValue(condition, value, tag, uses.length);
  }

  @override
  HInstruction visitIf(HIf node) {
    HInstruction condition = node.condition;
    if (condition is HConstant) return node;

    AbstractBool isTruthy = _abstractValueDomain.isTruthy(
      condition.instructionType,
    );
    if (isTruthy.isDefinitelyTrue) {
      _metrics.countConditionDecided.add();
      return _replaceHIfCondition(
        node,
        _graph.addConstantBool(true, _closedWorld),
      );
    } else if (isTruthy.isDefinitelyFalse) {
      _metrics.countConditionDecided.add();
      return _replaceHIfCondition(
        node,
        _graph.addConstantBool(false, _closedWorld),
      );
    }

    HBasicBlock thenBlock = node.thenBlock;
    HBasicBlock elseBlock = node.elseBlock;

    // For diamond control flow, if the end of the then- or else-block is not
    // reachable, the other block dynamically dominates the join, so the join
    // acts as a continuation of the else- or then- branch.
    HBasicBlock? thenContinuation;
    HBasicBlock? elseContinuation;
    if (node.joinBlock != null) {
      final joinPredecessors = node.joinBlock!.predecessors;
      if (joinPredecessors.length == 2) {
        if (hasUnreachableExit(joinPredecessors[0])) {
          elseContinuation = node.joinBlock;
        } else if (hasUnreachableExit(joinPredecessors[1])) {
          thenContinuation = node.joinBlock;
        }
      }
    }

    simplifyCondition(thenBlock, condition, true, 'then');
    simplifyCondition(thenContinuation, condition, true, 'then-join');
    simplifyCondition(elseBlock, condition, false, 'else');
    simplifyCondition(elseContinuation, condition, false, 'else-join');

    if (condition is HNot) {
      //  if (!t1) ... t1 ...
      HInstruction negated = condition.inputs[0];
      simplifyCondition(thenBlock, negated, false, 'then');
      simplifyCondition(thenContinuation, negated, false, 'then-join');
      simplifyCondition(elseBlock, negated, true, 'else');
      simplifyCondition(elseContinuation, negated, true, 'else-join');
    } else {
      // It is possible for LICM to move a negated version of the condition out
      // of the loop where it used. We still want to simplify the nested use of
      // the condition in that case, so we look for all dominating negated
      // conditions and replace nested uses of them with true or false.
      //
      //     t1 = ...
      //     t2 = !t1
      //     loop
      //       if (t1)
      //         t2     // replace with `false`
      //
      Iterable<HInstruction> dominating = condition.usedBy.where(
        (user) => user is HNot && user.dominates(node),
      );
      for (var hoisted in dominating) {
        simplifyCondition(thenBlock, hoisted, false, 'hoisted-then');
        simplifyCondition(
          thenContinuation,
          hoisted,
          false,
          'hoisted-then-join',
        );
        simplifyCondition(elseBlock, hoisted, true, 'hoisted-else');
        simplifyCondition(elseContinuation, hoisted, true, 'hoisted-else-join');
      }
    }

    return node;
  }

  /// Returns [node] after replacing condition.
  HInstruction _replaceHIfCondition(HIf node, HInstruction newCondition) {
    node.replaceInput(0, newCondition);
    return node;
  }

  @override
  HInstruction visitPrimitiveCheck(HPrimitiveCheck node) {
    if (node.isRedundant(_closedWorld)) return node.checkedInput;
    return node;
  }

  @override
  HInstruction visitNullCheck(HNullCheck node) {
    if (node.isRedundant(_closedWorld)) return node.checkedInput;
    return node;
  }

  @override
  HInstruction visitLateReadCheck(HLateReadCheck node) {
    if (node.isRedundant(_closedWorld)) return node.checkedInput;
    return node;
  }

  @override
  HInstruction visitLateWriteOnceCheck(HLateWriteOnceCheck node) {
    if (node.isRedundant(_closedWorld)) return node.checkedInput;
    return node;
  }

  @override
  HInstruction visitLateInitializeOnceCheck(HLateInitializeOnceCheck node) {
    if (node.isRedundant(_closedWorld)) return node.checkedInput;
    return node;
  }

  @override
  HInstruction visitTypeKnown(HTypeKnown node) {
    if (node.isRedundant(_closedWorld)) return node.checkedInput;
    return node;
  }

  @override
  HInstruction visitFieldGet(HFieldGet node) {
    var receiver = node.receiver;

    // HFieldGet of a constructed constant can be replaced with the constant's
    // field.
    if (receiver is HConstant) {
      ConstantValue constant = receiver.constant;
      if (constant is ConstructedConstantValue) {
        final value = constant.fields[node.element];
        if (value != null) {
          _metrics.countFieldGetFolded.add();
          return _graph.addConstant(value, _closedWorld);
        }
      }
      if (constant is RecordConstantValue) {
        final recordData = _closedWorld.recordData;
        final shape = constant.shape;
        final representation = recordData.representationForShape(shape);
        if (representation != null) {
          // The `representation` does not have a method to convert a field into
          // a record-index, so look at all the possible access paths to find
          // one that matches the field. Although this is 'slow' (1) only short
          // records have direct fields (longer ones use arrays), and (2) we
          // should always find a matching path, so the search will not be
          // repeated in later phases.
          for (int i = 0; i < constant.shape.fieldCount; i++) {
            final path = recordData.pathForAccess(shape, i);
            if (path.field == node.element && path.index == null) {
              return _graph.addConstant(constant.values[i], _closedWorld);
            }
          }
        }
      }
    }

    return node;
  }

  @override
  HInstruction visitGetLength(HGetLength node) {
    HInstruction receiver = node.receiver;

    if (receiver is HConstant) {
      ConstantValue constant = receiver.constant;
      if (constant is ListConstantValue) {
        _metrics.countGetLengthFolded.add();
        return _graph.addConstantInt(constant.length, _closedWorld);
      }
      if (constant is StringConstantValue) {
        _metrics.countGetLengthFolded.add();
        return _graph.addConstantInt(constant.length, _closedWorld);
      }
    }

    AbstractValue receiverType = receiver.instructionType;
    if (_abstractValueDomain.isContainer(receiverType)) {
      int? length = _abstractValueDomain.getContainerLength(receiverType);
      if (length != null) {
        HInstruction constant = _graph.addConstantInt(length, _closedWorld);
        _metrics.countGetLengthFolded.add();
        if (_abstractValueDomain.isNull(receiverType).isPotentiallyTrue) {
          // If the container can be null, we update all uses of the length
          // access to use the constant instead, but keep the length access in
          // the graph, to ensure we still have a null check.
          node.block!.rewrite(node, constant);
          return node;
        }
        return constant;
      }
    }

    // Can we find the length as an input to an allocation?
    HInstruction potentialAllocation = receiver;

    SCAN:
    while (!_graph.allocatedFixedLists.contains(potentialAllocation)) {
      switch (potentialAllocation) {
        case HInvokeStatic(:final element)
            when element == commonElements.setArrayType:
          // Look through `setArrayType(new Array(), ...)`
          potentialAllocation = potentialAllocation.inputs.first;
        case HArrayFlagsCheck(:final array) || HArrayFlagsSet(:final array):
          potentialAllocation = array;
        default:
          break SCAN;
      }
    }

    if (_graph.allocatedFixedLists.contains(potentialAllocation)) {
      // TODO(sra): How do we keep this working if we lower/inline the receiver
      // in an optimization?

      HInstruction lengthInput = potentialAllocation.inputs.first;

      // We don't expect a non-integer first input to the fixed-size allocation,
      // but checking the input is an integer ensures we do not replace a
      // HGetlength with a reference to something with a type that will confuse
      // bounds check elimination.
      if (lengthInput.isInteger(_abstractValueDomain).isDefinitelyTrue) {
        // TODO(sra). HGetLength may have a better type than [lengthInput] as
        // the allocation may throw on an out-of-range input. Typically the
        // input is an unconstrained `int` and the length is non-negative. We
        // may have done some optimizations with the better type that we won't
        // be able to do with the broader type of [lengthInput].  We should
        // insert a HTypeKnown witnessed by the allocation to narrow the
        // lengthInput.
        _metrics.countGetLengthFolded.add();
        return lengthInput;
      }
    }

    if (node.isAssignable &&
        isFixedLength(receiver.instructionType, _closedWorld)) {
      // The input type has changed to fixed-length so change to an unassignable
      // HGetLength to allow more GVN optimizations.
      _metrics.countGetLengthFolded.add();
      return HGetLength(receiver, node.instructionType, isAssignable: false);
    }
    return node;
  }

  @override
  HInstruction visitIndex(HIndex node) {
    switch (node) {
      case HIndex(
        receiver: HConstant(:final constant),
        index: HConstant(constant: final constantIndex),
      ):
        final foldedValue = constant_system.index.fold(constant, constantIndex);
        if (foldedValue != null) {
          _metrics.countIndexFolded.add();
          return _graph.addConstant(foldedValue, _closedWorld);
        }

      // Match the access path `(constant_record._values)[i]` for 'long' records
      // where the record fields are stored in an Array (the `_RecordN` family
      // of representations).
      case HIndex(
            receiver: HFieldGet(
              receiver: HConstant(
                constant: RecordConstantValue(:final shape, :final values),
              ),
              element: final field,
            ),
            index: HConstant(
              constant: IntConstantValue(:final intValue) &&
                  final constantIndex,
            ),
          )
          when constantIndex.isUInt31():
        int indexValue = intValue.toInt();
        final recordData = _closedWorld.recordData;
        final representation = recordData.representationForShape(shape);
        if (representation != null) {
          // We assume that the record index is going to be the same as the
          // HIndex index. If not (for example, we put the shape in the first
          // slot of the array, offsetting the record field indexes), the
          // codegen test will fail.
          final path = recordData.pathForAccess(shape, indexValue);
          if (path.field == field && path.index == indexValue) {
            return _graph.addConstant(values[indexValue], _closedWorld);
          }
        }
    }

    return node;
  }

  @override
  HInstruction visitCharCodeAt(HCharCodeAt node) {
    final folded = foldBinary(
      constant_system.codeUnitAt,
      node.receiver,
      node.index,
    );
    if (folded != null) return folded;
    return node;
  }

  /// Returns the guarded receiver.
  HInstruction maybeGuardWithNullCheck(
    HInstruction receiver,
    HInvokeDynamic node,
    FieldEntity? field,
  ) {
    AbstractValue receiverType = receiver.instructionType;
    if (_abstractValueDomain.isNull(receiverType).isPotentiallyTrue) {
      HNullCheck check =
          HNullCheck(receiver, _abstractValueDomain.excludeNull(receiverType))
            ..selector = node.selector
            ..field = field
            ..sourceInformation = node.sourceInformation;
      _log?.registerNullCheck(node, check);
      node.block!.addBefore(node, check);
      return check;
    }
    return receiver;
  }

  @override
  HInstruction visitInvokeDynamicGetter(HInvokeDynamicGetter node) {
    propagateConstantValueToUses(node);
    if (node.isInterceptedCall) {
      HInstruction folded = handleInterceptedCall(node);
      if (folded != node) return folded;
    }
    HInstruction receiver = node.getDartReceiver(_closedWorld);
    AbstractValue receiverType = receiver.instructionType;

    Selector selector = node.selector;
    final member =
        node.element ?? _closedWorld.locateSingleMember(selector, receiverType);
    if (member == null) return node;

    if (member is FieldEntity) {
      FieldEntity field = member;
      FieldAnalysisData fieldData = _closedWorld.fieldAnalysis.getFieldData(
        field,
      );
      if (fieldData.isEffectivelyConstant) {
        // The field is elided and replace it with its constant value.
        maybeGuardWithNullCheck(receiver, node, null);
        ConstantValue constant = fieldData.constantValue!;
        HConstant result = _graph.addConstant(
          constant,
          _closedWorld,
          sourceInformation: node.sourceInformation,
        );
        _metrics.countGettersElided.add();
        _log?.registerConstantFieldGet(node, field, result);
        return result;
      } else {
        receiver = maybeGuardWithNullCheck(receiver, node, field);
        HFieldGet result = _directFieldGet(receiver, field, node);
        _metrics.countGettersInlined.add();
        _log?.registerFieldGet(node, result);
        return result;
      }
    }

    if (member is FunctionEntity) {
      // If the member is not a getter, this could be a property extraction
      // getter or legacy `noSuchMethod`.
      if (member.isGetter && member.name == selector.name) {
        node.element = member;
        if (_nativeData.isNativeMember(member)) {
          return tryInlineNativeGetter(node, member) ?? node;
        }
      }
    }

    if (member.isFunction && member.name == selector.name) {
      // A property extraction getter, aka a tear-off.
      node.element = member;
      node.sideEffects.clearAllDependencies();
      node.sideEffects.clearAllSideEffects();
      node.setUseGvn(); // We don't care about identity of tear-offs.
    }
    return node;
  }

  HFieldGet _directFieldGet(
    HInstruction receiver,
    FieldEntity field,
    HInstruction node,
  ) {
    bool isAssignable = !_closedWorld.fieldNeverChanges(field);

    AbstractValue type;
    if (_nativeData.isNativeClass(field.enclosingClass!)) {
      type = AbstractValueFactory.fromNativeBehavior(
        _nativeData.getNativeFieldLoadBehavior(field),
        _closedWorld,
      );
    } else {
      // TODO(johnniwinther): Use the potentially more precise type of the
      // node + find a test that shows its usefulness.
      // type = _abstractValueDomain.intersection(
      //     node.instructionType,
      //     AbstractValueFactory.inferredTypeForMember(
      //         field, _globalInferenceResults));
      type = AbstractValueFactory.inferredTypeForMember(
        field,
        _globalInferenceResults,
      );
    }

    return HFieldGet(
      field,
      receiver,
      type,
      node.sourceInformation,
      isAssignable: isAssignable,
    );
  }

  @override
  HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
    if (node.isInterceptedCall) {
      HInstruction folded = handleInterceptedCall(node);
      if (folded != node) return folded;
    }

    HInstruction receiver = node.getDartReceiver(_closedWorld);
    AbstractValue receiverType = receiver.instructionType;
    final member = node.element ??= _closedWorld.locateSingleMember(
      node.selector,
      receiverType,
    );
    if (member == null) return node;

    if (member is FieldEntity) {
      if (!member.isAssignable) return node;
      // Use `node.inputs.last` in case the call follows the interceptor calling
      // convention, but is not a call on an interceptor.
      HInstruction value = node.inputs.last;

      HInstruction assignField() {
        if (_closedWorld.fieldAnalysis.getFieldData(member).isElided) {
          _log?.registerFieldSet(node);
          _metrics.countSettersElided.add();
          return value;
        } else {
          HFieldSet result = HFieldSet(member, receiver, value)
            ..sourceInformation = node.sourceInformation;
          _log?.registerFieldSet(node, result);
          _metrics.countSettersInlined.add();
          return result;
        }
      }

      if (node.isInvariant &&
          !_closedWorld.elementEnvironment.isFieldCovariantByDeclaration(
            member,
          )) {
        return assignField();
      }

      if (!_closedWorld.annotationsData
          .getParameterCheckPolicy(member)
          .isEmitted) {
        return assignField();
      }

      DartType fieldType = _closedWorld.elementEnvironment.getFieldType(member);

      AbstractValueWithPrecision checkedType = _abstractValueDomain
          .createFromStaticType(fieldType);
      if (checkedType.isPrecise &&
          _abstractValueDomain
              .isIn(value.instructionType, checkedType.abstractValue)
              .isDefinitelyTrue) {
        return assignField();
      }
      // TODO(sra): Implement inlining of setters with checks for new rti. The
      // check and field assignment for the setter should be inlined if this is
      // the only call to the setter, or the current function already computes
      // the type of the field.
      node.needsCheck = true;
      return node;
    }

    if (member is FunctionEntity) {
      // If the member is not a setter is could be legacy `noSuchMethod`.
      if (member.isSetter && member.name == node.selector.name) {
        if (_nativeData.isNativeMember(member)) {
          return tryInlineNativeSetter(node, member) ?? node;
        }
      }
    }

    return node;
  }

  @override
  HInstruction visitInvokeClosure(HInvokeClosure node) {
    HInstruction closure = node.getDartReceiver(_closedWorld);

    // Replace indirect call to static method tear-off closure with direct call
    // to static method.
    if (closure is HConstant) {
      ConstantValue constant = closure.constant;
      if (constant is FunctionConstantValue) {
        FunctionEntity target = constant.element;
        ParameterStructure parameterStructure = target.parameterStructure;
        if (parameterStructure.callStructure == node.selector.callStructure) {
          // TODO(sra): Handle adding optional arguments default values.
          assert(!node.isInterceptedCall);
          return HInvokeStatic(
            target,
            node.inputs.skip(1).toList(),
            node.instructionType,
            node.typeArguments,
          )..sourceInformation = node.sourceInformation;
        }
      }
    }
    return node;
  }

  @override
  HInstruction visitInvokeStatic(HInvokeStatic node) {
    propagateConstantValueToUses(node);
    MemberEntity element = node.element;

    if (element == commonElements.identicalFunction) {
      if (node.inputs.length == 2) {
        return HIdentity(
          node.inputs[0],
          node.inputs[1],
          _abstractValueDomain.boolType,
        )..sourceInformation = node.sourceInformation;
      }
    } else if (element == commonElements.setArrayType) {
      if (node.inputs.length == 2) {
        return handleArrayTypeInfo(node);
      }
    } else if (commonElements.isCheckConcurrentModificationError(element)) {
      if (node.inputs.length == 2) {
        HInstruction firstArgument = node.inputs[0];
        if (firstArgument is HConstant) {
          HConstant constant = firstArgument;
          if (constant.constant is TrueConstantValue) return constant;
        }
      }
    } else if (commonElements.isCheckInt(element)) {
      if (node.inputs.length == 1) {
        HInstruction argument = node.inputs[0];
        if (argument.isInteger(_abstractValueDomain).isDefinitelyTrue) {
          return argument;
        }
      }
    } else if (commonElements.isCheckNum(element)) {
      if (node.inputs.length == 1) {
        HInstruction argument = node.inputs[0];
        if (argument.isNumber(_abstractValueDomain).isDefinitelyTrue) {
          return argument;
        }
      }
    } else if (commonElements.isCheckString(element)) {
      if (node.inputs.length == 1) {
        HInstruction argument = node.inputs[0];
        if (argument.isString(_abstractValueDomain).isDefinitelyTrue) {
          return argument;
        }
      }
    } else {
      final isAssertHelper = commonElements.isAssertHelper(element);
      final isAssertTest = commonElements.isAssertTest(element);
      if (isAssertHelper || isAssertTest) {
        if (node.inputs.length == 1) {
          HInstruction argument = node.inputs[0];
          if (argument is HConstant) {
            ConstantValue constant = argument.constant;
            if (constant is BoolConstantValue) {
              bool value = constant is TrueConstantValue;
              if (isAssertTest) {
                // `assertTest(argument)` effectively negates the argument.
                return _graph.addConstantBool(!value, _closedWorld);
              }
              // `assertHelper(true)` is a no-op, other values throw.
              if (value) return argument;
            }
          }
        }
      }
    }

    // TODO(sra): [element] could be a native or js-interop method, in which
    // case we could 'inline' the call to the Dart-convention wrapper code,
    // replacing it with a HInvokeExternal instruction. Many of these static
    // methods are already 'inlined' by the CFG builder.

    return node;
  }

  HInstruction handleArrayTypeInfo(HInvokeStatic node) {
    // If type information is not needed, use the raw Array.
    HInstruction source = node.inputs[0];
    if (source.usedBy.length != 1) return node;
    if (source.isArray(_abstractValueDomain).isPotentiallyFalse) {
      return node;
    }
    for (HInstruction user in node.usedBy) {
      if (user is HGetLength) continue;
      if (user is HIndex) continue;
      // Bounds check escapes the array, but we don't care.
      if (user is HBoundsCheck) continue;
      // Interceptor only escapes the Array if array passed to an intercepted
      // method.
      if (user is HInterceptor) continue;
      if (user is HInvokeStatic) {
        MemberEntity element = user.element;
        if (commonElements.isCheckConcurrentModificationError(element)) {
          // CME check escapes the array, but we don't care.
          continue;
        }
      }
      if (user is HInvokeDynamicGetter) {
        String name = user.selector.name;
        // These getters don't use the Array type.
        if (name == 'last') continue;
        if (name == 'first') continue;
      }
      // TODO(sra): Implement a more general algorithm - many methods don't use
      // the element type.
      return node;
    }
    return source;
  }

  @override
  HInstruction visitStringConcat(HStringConcat node) {
    // Simplify string concat:
    //
    //     "" + R                ->  R
    //     L + ""                ->  L
    //     "L" + "R"             ->  "LR"
    //     (prefix + "L") + "R"  ->  prefix + "LR"
    //
    StringConstantValue? getString(HInstruction instruction) {
      if (instruction is HConstant) {
        final constant = instruction.constant;
        if (constant is StringConstantValue) return constant;
      }
      return null;
    }

    final left = node.left;
    final right = node.right;
    StringConstantValue? leftString = getString(left);
    if (leftString != null && leftString.stringValue.isEmpty) {
      return right;
    }

    final rightString = getString(right);
    if (rightString == null) return node;
    if (rightString.stringValue.isEmpty) return left;

    HInstruction? prefix;
    if (leftString == null) {
      if (left is! HStringConcat) return node;
      HStringConcat leftConcat = left;
      // Don't undo CSE.
      if (leftConcat.usedBy.length != 1) return node;
      prefix = leftConcat.left;
      leftString = getString(leftConcat.right);
      if (leftString == null) return node;
    }

    if (leftString.stringValue.length + rightString.stringValue.length >
        maxSharedConstantFoldedStringLength) {
      if (node.usedBy.length > 1) return node;
    }

    HInstruction folded = _graph.addConstant(
      constant_system.createString(
        leftString.stringValue + rightString.stringValue,
      ),
      _closedWorld,
    );
    if (prefix == null) return folded;
    return HStringConcat(prefix, folded, _abstractValueDomain.stringType);
  }

  @override
  HInstruction visitStringify(HStringify node) {
    HInstruction input = node.inputs[0];
    if (input.isString(_abstractValueDomain).isDefinitelyTrue) {
      return input;
    }

    HInstruction asString(String string) =>
        _graph.addConstant(constant_system.createString(string), _closedWorld);

    HInstruction? tryConstant() {
      if (input is HConstant) {
        ConstantValue value = input.constant;
        if (value is IntConstantValue) {
          // Only constant-fold int.toString() when Dart and JS results the
          // same.
          // TODO(18103): We should be able to remove this workaround when
          // issue 18103 is resolved by providing the correct string.
          if (!value.isUInt32()) return null;
          return asString('${value.intValue}');
        }
        if (value is BoolConstantValue) {
          return asString(value.boolValue ? 'true' : 'false');
        }
        if (value is NullConstantValue) {
          return asString('null');
        }
        if (value is DoubleConstantValue) {
          // TODO(sra): It seems unlikely that all dart2js host implementations
          // produce exactly the same characters as all JavaScript targets.
          return asString('${value.doubleValue}');
        }
      }
      return null;
    }

    HInstruction? tryToString() {
      // If the `toString` method is guaranteed to return a string we can call
      // it directly. Keep the stringifier for primitives (since they have fast
      // path code in the stringifier) and for classes requiring interceptors
      // (since SsaInstructionSimplifier runs after SsaSimplifyInterceptors).
      if (input.isPrimitive(_abstractValueDomain).isPotentiallyTrue) {
        return null;
      }
      if (input.isNull(_abstractValueDomain).isPotentiallyTrue) {
        return null;
      }
      Selector selector = Selectors.toString_;
      AbstractValue toStringType =
          AbstractValueFactory.inferredResultTypeForSelector(
            selector,
            input.instructionType,
            _globalInferenceResults,
          );
      if (_abstractValueDomain
          .containsOnlyType(
            toStringType,
            _closedWorld.commonElements.jsStringClass,
          )
          .isPotentiallyFalse) {
        return null;
      }
      // All intercepted classes extend `Interceptor`, so if the receiver can't
      // be a class extending `Interceptor` then it can be called directly.
      if (_abstractValueDomain
          .isInterceptor(input.instructionType)
          .isDefinitelyFalse) {
        List<HInstruction> inputs = [input, input]; // [interceptor, receiver].
        HInstruction result = HInvokeDynamicMethod(
          selector,
          input.instructionType, // receiver type.
          inputs,
          toStringType,
          const <DartType>[],
          node.sourceInformation,
          isIntercepted: true,
        );
        return result;
      }
      return null;
    }

    // For primitives we know the stringifier is effect-free and never throws.
    if (input.isNumberOrNull(_abstractValueDomain).isDefinitelyTrue ||
        input.isStringOrNull(_abstractValueDomain).isDefinitelyTrue ||
        input.isBooleanOrNull(_abstractValueDomain).isDefinitelyTrue) {
      node.setPure();
    }

    return tryConstant() ?? tryToString() ?? node;
  }

  @override
  HInstruction visitOneShotInterceptor(HOneShotInterceptor node) {
    throw StateError('Should not see HOneShotInterceptor in simplifier: $node');
  }

  @override
  HInstruction visitTypeEval(HTypeEval node) {
    HInstruction environment = node.inputs.single;
    if (_typeRecipeDomain.isIdentity(node.typeExpression, node.envStructure)) {
      return environment;
    }

    if (environment is HLoadType) {
      final result = _typeRecipeDomain.foldLoadEval(
        environment.typeExpression,
        node.envStructure,
        node.typeExpression,
      );
      if (result != null) return HLoadType(result, node.instructionType);
      return node;
    }

    if (environment is HTypeBind) {
      HInstruction bindings = environment.inputs.last;
      if (bindings is HLoadType) {
        //  env.bind(LoadType(T)).eval(...1...)  -->  env.eval(...T...)
        final result = _typeRecipeDomain.foldBindLoadEval(
          bindings.typeExpression,
          node.envStructure,
          node.typeExpression,
        );
        if (result != null) {
          HInstruction previousEnvironment = environment.inputs.first;
          return HTypeEval(
            previousEnvironment,
            result.environmentStructure,
            result.recipe,
            node.instructionType,
          );
        }
      }
      // TODO(sra):  LoadType(T).bind(E).eval(...1...) --> E.eval(...0...)
      return node;
    }

    if (environment is HTypeEval) {
      final result = _typeRecipeDomain.foldEvalEval(
        environment.envStructure,
        environment.typeExpression,
        node.envStructure,
        node.typeExpression,
      );
      if (result != null) {
        HInstruction previousEnvironment = environment.inputs.first;
        return HTypeEval(
          previousEnvironment,
          result.environmentStructure,
          result.recipe,
          node.instructionType,
        );
      }
      return node;
    }

    if (environment is HInstanceEnvironment) {
      HInstruction instance = environment.inputs.single;
      AbstractValue instanceAbstractValue = instance.instructionType;
      ClassEntity? instanceClass;

      // All the subclasses of JSArray are JSArray at runtime.
      ClassEntity jsArrayClass = _closedWorld.commonElements.jsArrayClass;
      if (_abstractValueDomain
          .isInstanceOf(instanceAbstractValue, jsArrayClass)
          .isDefinitelyTrue) {
        instanceClass = jsArrayClass;
      } else {
        instanceClass = _abstractValueDomain.getExactClass(
          instanceAbstractValue,
        );
      }
      if (instanceClass != null) {
        if (_typeRecipeDomain.isReconstruction(
          instanceClass,
          node.envStructure,
          node.typeExpression,
        )) {
          return environment;
        }
      }
    }

    return node;
  }

  @override
  HInstruction visitTypeBind(HTypeBind node) {
    final environment = node.inputs[0];
    final argument = node.inputs[1];
    if (environment is HTypeEval &&
        argument is HTypeEval &&
        environment.inputs.single == argument.inputs.single &&
        // Should always be true, but checking is safe:
        TypeEnvironmentStructure.same(
          environment.envStructure,
          argument.envStructure,
        )) {
      //  env.eval(X).bind(env.eval(Y)) --> env.eval(...X...Y...)
      final result = _typeRecipeDomain.foldEvalBindEvalWithSharedEnvironment(
        environment.envStructure,
        environment.typeExpression,
        argument.typeExpression,
      );
      if (result != null) {
        return HTypeEval(
          environment.inputs.single,
          result.environmentStructure,
          result.recipe,
          node.instructionType,
        );
      }
    }
    return node;
  }

  @override
  HInstruction visitAsCheck(HAsCheck node) {
    // TODO(fishythefish): Correctly constant fold `null as T` (also in
    // [visitAsCheckSimple]) when running with sound null safety. We might get
    // this for free if nullability is precisely propagated to the typemasks.

    HInstruction typeInput = node.typeInput;
    if (typeInput is HLoadType) {
      // Always a TypeExpressionRecipe, otherwise 'as' is malformed.
      TypeExpressionRecipe recipe =
          typeInput.typeExpression as TypeExpressionRecipe;
      node.checkedTypeExpression = recipe.type;
    }

    if (node.isRedundant(_closedWorld, _options)) {
      return node.checkedInput;
    }

    // See if this check can be lowered to a simple one.
    final specializedCheck = SpecializedChecks.findAsCheck(
      node.checkedTypeExpression,
      _closedWorld.commonElements,
    );
    if (specializedCheck != null) {
      AbstractValueWithPrecision checkedType = _abstractValueDomain
          .createFromStaticType(node.checkedTypeExpression);
      return HAsCheckSimple(
        node.checkedInput,
        node.checkedTypeExpression,
        checkedType,
        node.isTypeError,
        specializedCheck,
        node.instructionType,
      );
    }
    return node;
  }

  @override
  HInstruction visitAsCheckSimple(HAsCheckSimple node) {
    if (node.isRedundant(_closedWorld, _options)) {
      return node.checkedInput;
    }
    return node;
  }

  @override
  HInstruction visitIsTest(HIsTest node) {
    HInstruction typeInput = node.typeInput;
    if (typeInput is HLoadType) {
      // Always a TypeExpressionRecipe, otherwise 'is' is malformed.
      TypeExpressionRecipe recipe =
          typeInput.typeExpression as TypeExpressionRecipe;
      node.dartType = recipe.type;
    }

    AbstractBool result = node.evaluate(_closedWorld, _options);
    if (result.isDefinitelyFalse) {
      _metrics.countIsTestDecided.add();
      return _graph.addConstantBool(false, _closedWorld);
    }
    if (result.isDefinitelyTrue) {
      _metrics.countIsTestDecided.add();
      return _graph.addConstantBool(true, _closedWorld);
    }

    final specialization = SpecializedChecks.findIsTestSpecialization(
      node.dartType,
      _graph.element,
      _closedWorld,
    );

    if (specialization == SimpleIsTestSpecialization.isNull ||
        specialization == SimpleIsTestSpecialization.isNotNull) {
      HInstruction nullTest = HIdentity(
        node.checkedInput,
        _graph.addConstantNull(_closedWorld),
        _abstractValueDomain.boolType,
      );
      if (specialization == SimpleIsTestSpecialization.isNull) return nullTest;
      nullTest.sourceInformation = node.sourceInformation;
      node.block!.addBefore(node, nullTest);
      return HNot(nullTest, _abstractValueDomain.boolType);
    }

    if (specialization != null) {
      AbstractValueWithPrecision checkedType = _abstractValueDomain
          .createFromStaticType(node.dartType);
      _metrics.countIsTestSimplified.add();
      return HIsTestSimple(
        node.dartType,
        checkedType,
        specialization,
        node.checkedInput,
        _abstractValueDomain.boolType,
      );
    }

    // TODO(fishythefish): Prune now-unneeded is-tests from the metadata.

    return node;
  }

  @override
  HInstruction visitIsTestSimple(HIsTestSimple node) {
    AbstractBool result = node.evaluate(_closedWorld, _options);
    if (result.isDefinitelyFalse) {
      _metrics.countIsTestDecided.add();
      return _graph.addConstantBool(false, _closedWorld);
    }
    if (result.isDefinitelyTrue) {
      _metrics.countIsTestDecided.add();
      return _graph.addConstantBool(true, _closedWorld);
    }
    return node;
  }

  @override
  HInstruction visitInstanceEnvironment(HInstanceEnvironment node) {
    HInstruction instance = node.inputs.single.nonCheck();

    // Store-forward instance types of created instances and constant instances.
    //
    // Forwarding the type might cause the instance (HCreate, constant etc) to
    // become dead. This might cause us to lose track of that fact that there
    // are type expressions from within the instance's class scope, so breaking
    // the algorithm for generating the per-type runtime type information. The
    // fix is to register the classes as created here in case the instance
    // becomes dead.
    //
    // TODO(sra): It would be cleaner to track on HLoadType, HTypeEval, etc
    // which class scope(s) they originated from. If the type expressions become
    // dead, the references to the scope type variables become dead.

    if (instance is HCreate) {
      if (instance.hasRtiInput) {
        instance.instantiatedTypes?.forEach(_registry.registerInstantiation);
        return instance.rtiInput;
      }
      InterfaceType instanceType = _closedWorld.elementEnvironment.getThisType(
        instance.element,
      );
      if (instanceType.typeArguments.isEmpty) {
        instance.instantiatedTypes?.forEach(_registry.registerInstantiation);
        return HLoadType.type(instanceType, instance.instructionType);
      }
      return node;
    }

    if (instance is HConstant) {
      ConstantValue constantValue = instance.constant;
      if (constantValue is ConstructedConstantValue) {
        _registry.registerInstantiation(constantValue.type);
        return HLoadType.type(constantValue.type, instance.instructionType);
      }
      if (constantValue is ListConstantValue) {
        InterfaceType type = constantValue.type;
        _registry.registerInstantiation(type);
        return HLoadType.type(type, instance.instructionType);
      }
      return node;
    }

    if (instance is HInvokeStatic &&
        instance.element == commonElements.setArrayType) {
      // TODO(sra): What is the 'instantiated type' we should be registering as
      // discussed above? Perhaps it should be carried on HLiteralList.
      return instance.inputs.last;
    }

    return node;
  }

  @override
  HInstruction visitBitAnd(HBitAnd node) {
    HInstruction left = node.left;
    HInstruction right = node.right;

    if (left is HConstant) {
      if (right is HConstant) {
        return foldBinary(node.operation(), left, right) ?? node;
      }
      //  c1 & a  -->  a & c1
      return HBitAnd(right, left, node.instructionType);
    }

    if (right is HConstant) {
      ConstantValue constant = right.constant;
      if (constant.isZero) return right; // a & 0  -->  0
      if (_isFull32BitMask(constant)) {
        if (left.isUInt32(_abstractValueDomain).isDefinitelyTrue) {
          // Mask of all '1's has no effect.
          return left;
          // TODO(sra): A more advanced version of this would be to see if the
          // input might have any bits that would be cleared by the mask.  Thus
          // `a >> 24 & 255` is a no-op since `a >> 24` can have only the low 8
          // bits non-zero. If a bit is must-zero, we can remove it from
          // mask. e.g. if a is Uint31, then `a >> 24 & 0xF0` becomes `a >> 24 &
          // 0x70`.
        }

        // Ensure that the result is still canonicalized to an unsigned 32-bit
        // integer using `left >>> 0`. This shift is often removed or combined
        // in subsequent optimization.
        HConstant zero = _graph.addConstantInt(0, _closedWorld);
        return HShiftRight(left, zero, node.instructionType);
      }

      if (left is HBitAnd && left.usedBy.length == 1) {
        HInstruction operand1 = left.left;
        HInstruction operand2 = left.right;
        if (operand2 is HConstant) {
          //  (a & c1) & c2  -->  a & (c1 & c2)
          final folded = foldBinary(constant_system.bitAnd, operand2, right);
          if (folded == null) return node;
          return HBitAnd(operand1, folded, node.instructionType);
        }
        // TODO(sra): We don't rewrite (a & c1) & b --> (a & b) & c1. I suspect
        // that the JavaScript VM might benefit from reducing the value early
        // (e.g. to a 'Smi'). We could do that, but we should also consider a
        // variation of the above rule where:
        //
        //     a & c1 & ... & b & c2  -->  a & (c1 & c2) & ... & b
        //
        // This would probably be best deferred until after GVN in case (a & c1)
        // is reused.
      }
    }

    return node;
  }

  bool _isFull32BitMask(ConstantValue constant) {
    return constant is IntConstantValue && constant.intValue == _mask32;
  }

  static final _mask32 = BigInt.parse('FFFFFFFF', radix: 16);

  @override
  HInstruction visitBitOr(HBitOr node) {
    HInstruction left = node.left;
    HInstruction right = node.right;

    if (left is HConstant) {
      if (right is HConstant) {
        return foldBinary(node.operation(), left, right) ?? node;
      }
      //  c1 | a  -->  a | c1
      return HBitOr(right, left, node.instructionType);
    }

    //  (a | b) | c
    if (left is HBitOr && left.usedBy.length == 1) {
      HInstruction operand1 = left.left;
      HInstruction operand2 = left.right;
      if (operand2 is HConstant) {
        if (right is HConstant) {
          //  (a | c1) | c2  -->  a | (c1 | c2)
          final folded = foldBinary(constant_system.bitOr, operand2, right);
          if (folded == null) return node;
          return HBitOr(operand1, folded, node.instructionType);
        } else {
          //  (a | c1) | b  -->  (a | b) | c1
          HInstruction or1 = _makeBitOr(operand1, right)
            ..sourceInformation = left.sourceInformation;
          node.block!.addBefore(node, or1);
          // TODO(sra): Restart simplification at 'or1'.
          return _makeBitOr(or1, operand2);
        }
      }
    }

    //  (a & c1) | (a & c2)  -->  a & (c1 | c2)
    if (left is HBitAnd &&
        left.usedBy.length == 1 &&
        right is HBitAnd &&
        right.usedBy.length == 1) {
      HInstruction a1 = left.left;
      HInstruction a2 = right.left;
      if (a1 == a2) {
        HInstruction c1 = left.right;
        HInstruction c2 = right.right;
        if (c1 is HConstant && c2 is HConstant) {
          final folded = foldBinary(constant_system.bitOr, c1, c2);
          if (folded != null) {
            return HBitAnd(a1, folded, node.instructionType);
          }
        }
      }
    }

    // TODO(sra):
    //
    //  (e | (a & c1)) | (a & c2)  -->  e | (a & (c1 | c2))

    return node;
  }

  HBitOr _makeBitOr(HInstruction operand1, HInstruction operand2) {
    AbstractValue instructionType = _abstractValueDomainBitOr(
      operand1.instructionType,
      operand2.instructionType,
    );
    return HBitOr(operand1, operand2, instructionType);
  }

  // TODO(sra): Use a common definition of primitive operations in the
  // AbstractValueDomain.
  AbstractValue _abstractValueDomainBitOr(AbstractValue a, AbstractValue b) {
    return (_abstractValueDomain.isUInt31(a).isDefinitelyTrue &&
            _abstractValueDomain.isUInt31(b).isDefinitelyTrue)
        ? _abstractValueDomain.uint31Type
        : _abstractValueDomain.uint32Type;
  }

  @override
  HInstruction visitShiftRight(HShiftRight node) {
    HInstruction left = node.left;
    HInstruction count = node.right;
    if (count is HConstant) {
      if (left is HConstant) {
        return foldBinary(node.operation(), left, count) ?? node;
      }
      ConstantValue countValue = count.constant;
      // Shift by zero can convert to 32 bit unsigned, so remove only if no-op.
      //  a >> 0  -->  a
      if (countValue.isZero &&
          left.isUInt32(_abstractValueDomain).isDefinitelyTrue) {
        return left;
      }
      if (left is HBitAnd && left.usedBy.length == 1) {
        // TODO(sra): Should this be postponed to after GVN?
        HInstruction operand = left.left;
        HInstruction mask = left.right;
        if (mask is HConstant) {
          // Reduce mask constant size.
          //  (a & mask) >> count  -->  (a >> count) & (mask >> count)
          ConstantValue maskValue = mask.constant;

          final shiftedMask = constant_system.shiftRight.fold(
            maskValue,
            countValue,
          );
          if (shiftedMask is IntConstantValue && shiftedMask.isUInt32()) {
            // TODO(sra): The shift type should be available from the abstract
            // value domain.
            AbstractValue shiftType = shiftedMask.isZero
                ? _abstractValueDomain.uint32Type
                : _abstractValueDomain.uint31Type;
            var shift = HShiftRight(operand, count, shiftType)
              ..sourceInformation = node.sourceInformation;

            node.block!.addBefore(node, shift);
            HConstant shiftedMaskInstruction = _graph.addConstant(
              shiftedMask,
              _closedWorld,
            );
            return HBitAnd(shift, shiftedMaskInstruction, node.instructionType);
          }
        }
        return node;
      }
    }
    return node;
  }

  @override
  HInstruction visitShiftLeft(HShiftLeft node) {
    HInstruction left = node.left;
    HInstruction count = node.right;
    if (count is HConstant) {
      if (left is HConstant) {
        return foldBinary(node.operation(), left, count) ?? node;
      }
      // Shift by zero can convert to 32 bit unsigned, so remove only if no-op.
      //  a << 0  -->  a
      if (count.constant.isZero &&
          left.isUInt32(_abstractValueDomain).isDefinitelyTrue) {
        return left;
      }
      // Shift-mask-unshift reduction.
      //   ((a >> c1) & c2) << c1  -->  a & (c2 << c1);
      if (left is HBitAnd && left.usedBy.length == 1) {
        HInstruction operand1 = left.left;
        HInstruction operand2 = left.right;
        if (operand2 is HConstant) {
          if (operand1 is HShiftRight && operand1.usedBy.length == 1) {
            HInstruction a = operand1.left;
            HInstruction count2 = operand1.right;
            if (count2 == count) {
              final folded = foldBinary(
                constant_system.shiftLeft,
                operand2,
                count,
              );
              if (folded != null) {
                return HBitAnd(a, folded, node.instructionType);
              }
            }
          }
        }
      }
    }
    return node;
  }

  @override
  HInstruction visitArrayFlagsCheck(HArrayFlagsCheck node) {
    // TODO(sra): Implement removal on basis of type, an 'isRedundant' check.

    final array = node.array;
    final arrayFlags = node.arrayFlags;
    final checkFlags = node.checkFlags;

    if (arrayFlags is HConstant && arrayFlags.constant.isZero) return array;

    if (array is HArrayFlagsCheck) {
      // Dependent check. Checks become dependent during types_propagation.
      if (arrayFlags == array.arrayFlags && checkFlags == array.checkFlags) {
        // Check is redundant, even if the `node.operation` is different
        // (different operations are not picked up by GVN).
        //
        // TODO(sra): If a stronger check dominates a weaker check (e.g. check
        // for immutable before check for fixed length), we can match that with
        // different flags.
        return array;
      }
    }

    // The 'operation' and 'verb' strings can be replaced with an index into a
    // small table to known operations or verbs. This makes the call-sites
    // smaller, so is worthwhile for calls to HArrayFlagsCheck that are inlined
    // into multiple places.
    //
    // A trailing zero index (verb, or verb and operation) can be omitted from
    // the instruction.
    //
    // When both indexes are replaced by indexes, the indexes are combined into
    // a single value.
    //
    //     finalIndex = verbIndex * numberOfOperationIndexes + operationIndex

    int? verbIndex; // Verb index if nonzero.

    if (node.hasVerb) {
      if (node.verb case HConstant(
        constant: StringConstantValue(:final stringValue),
      )) {
        final index = ArrayFlags.verbToIndex[stringValue];
        if (index != null) {
          if (index == 0) {
            node.removeInput(4);
          } else {
            final replacement = _graph.addConstantInt(index, _closedWorld);
            node.replaceInput(4, replacement);
            verbIndex = index;
          }
        }
      }
    }

    if (node.hasOperation) {
      if (node.operation case HConstant(
        constant: StringConstantValue(:final stringValue),
      )) {
        var index = ArrayFlags.operationNameToIndex[stringValue];
        if (index != null) {
          if (index == 0 && !node.hasVerb) {
            node.removeInput(3);
          } else {
            if (verbIndex != null) {
              // Encode combined indexes and remove 'verb' input.
              index += verbIndex * ArrayFlags.operationNameToIndex.length;
              node.removeInput(4);
            }
            final replacement = _graph.addConstantInt(index, _closedWorld);
            node.replaceInput(3, replacement);
          }
        }
      }
    }

    return node;
  }

  /// All HArrayFlagsGet instructions that depend on something. Used to promote
  /// `HArrayFlagsGet` instructions to side-effect insensitive.  See
  /// [finalizeArrayFlagEffects] for details.
  List<HArrayFlagsGet>? _arrayFlagsGets;
  bool _arrayFlagsEffect = false;

  @override
  HInstruction visitArrayFlagsSet(HArrayFlagsSet node) {
    _arrayFlagsEffect = true;
    return node;
  }

  @override
  HInstruction visitArrayFlagsGet(HArrayFlagsGet node) {
    if (node.sideEffects.dependsOnSomething()) {
      (_arrayFlagsGets ??= []).add(node);
    } else {
      // If the HArrayFlagsGet is pure and the source is visible, then there is
      // no HArrayFlagsSet instruction that changes the flags, so the flags are
      // `0`. This can remove checks on allocations in the same method. To do
      // this for typed arrays, we need to recognize the allocation.

      final array = node.inputs.single;

      if (array is HForeignCode) {
        final behavior = array.nativeBehavior;
        if (behavior != null && behavior.isAllocation) {
          return _graph.addConstantInt(ArrayFlags.none, _closedWorld);
        }
      }
    }

    // The following store-forwarding of the flags is valid only because all
    // code in the SDK has a 'linear' pattern where the original value is never
    // accessed after it is 'tagged' with the flags.
    HInstruction array = node.inputs.single;
    while (array is HArrayFlagsCheck) {
      array = array.array;
    }
    if (array case HArrayFlagsSet(:final flags)) return flags;

    return node;
  }

  void finalizeArrayFlagEffects() {
    // HArrayFlagsGet operations must not be moved past HArrayFlagsSet
    // operations on the same Array or typed data view. Initially we prevent
    // this by making HArrayFlagsSet have a changes-property side effect, and
    // making HArrayFlagsGet depend on that effect.
    //
    // This turns out to be rather restrictive and a general 'depends on
    // property' dependency inhibits important optimizations like hoisting
    // HArrayFlagsGet out of loops. We could try an add a new effect, but since
    // the effect analysis is not aware of (non)aliasing, the new effect would
    // largely have the same problem.
    //
    // Instead we notice that HArrayFlagsSet is rare: it is used to implement
    // constructors that initialize the data, and then mark it as unmodifiable
    // or fixed-length. If we invoke a callee that does a HArrayFlagsSet
    // operation, the target of that operation is not visible to the caller.
    //
    // Therefore we assume that if we can't see any HArrayFlagsSet operations in
    // the current method, they cannot change the value observed by
    // HArrayFlagsGet, and we can pretent the HArrayFlagsGets are pure.

    if (_arrayFlagsGets == null || _arrayFlagsEffect) return;

    for (final instruction in _arrayFlagsGets!) {
      // Instruction may have been removed from the CFG, but that is harmless.
      instruction.sideEffects.clearAllDependencies();
    }
  }
}

class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase {
  @override
  final String name = "SsaDeadCodeEliminator";

  final JClosedWorld closedWorld;
  final SsaOptimizerTask optimizer;
  late final HGraph _graph;
  Map<HInstruction, bool> trivialDeadStoreReceivers = Maplet();
  bool eliminatedSideEffects = false;
  bool newGvnCandidates = false;

  SsaDeadCodeEliminator(this.closedWorld, this.optimizer);

  AbstractValueDomain get _abstractValueDomain =>
      closedWorld.abstractValueDomain;

  // A constant with no type does not pollute types at phi nodes.
  late final HInstruction zapInstruction = _graph.addConstantUnreachable(
    closedWorld,
  );

  /// Determines whether we can delete [instruction] because the only thing it
  /// does is throw the same exception as the next instruction that throws or
  /// has an effect.
  bool canFoldIntoFollowingInstruction(HInstruction instruction) {
    assert(instruction.usedBy.isEmpty);
    assert(instruction.canThrow(_abstractValueDomain));

    if (!instruction.onlyThrowsNSM()) return false;

    final receiver = instruction.getDartReceiver(closedWorld);
    HInstruction? current = instruction.next;
    do {
      if ((current!.getDartReceiver(closedWorld) == receiver) &&
          current.canThrow(_abstractValueDomain)) {
        return true;
      }
      if (current is HForeignCode && current.isNullGuardFor(receiver)) {
        return true;
      }
      if (current.canThrow(_abstractValueDomain) ||
          current.sideEffects.hasSideEffects()) {
        return false;
      }

      HInstruction? next = current.next;
      if (next == null) {
        // We do not merge blocks in our SSA graph, so if this block just jumps
        // to a single successor, visit the successor, avoiding back-edges.
        HBasicBlock? successor;
        if (current is HGoto) {
          successor = current.block!.successors.single;
        } else if (current is HIf) {
          // We also leave HIf nodes in place when one branch is dead.
          HInstruction condition = current.inputs.first;
          if (condition is HConstant) {
            successor = condition.constant is TrueConstantValue
                ? current.thenBlock
                : current.elseBlock;
            assert(successor.isLive);
          }
        }
        if (successor != null && successor.id > current.block!.id) {
          next = successor.first;
        }
      }
      current = next;
    } while (current != null);
    return false;
  }

  bool isTrivialDeadStoreReceiver(HInstruction instruction) {
    // For an allocation, if all the loads are dead (awaiting removal after
    // SsaLoadElimination) and the only other uses are stores, then the
    // allocation does not escape which makes all the stores dead too.
    bool isDeadUse(HInstruction use) {
      if (use is HFieldSet) {
        // The use must be the receiver.  Even if the use is also the argument,
        // i.e.  a.x = a, the store is still dead if all other uses are dead.
        if (use.getDartReceiver(closedWorld) == instruction) return true;
      } else if (use is HFieldGet) {
        assert(use.getDartReceiver(closedWorld) == instruction);
        if (isDeadCode(use)) return true;
      }
      return false;
    }

    return instruction.isAllocation(_abstractValueDomain) &&
        instruction.isPure(_abstractValueDomain) &&
        trivialDeadStoreReceivers.putIfAbsent(
          instruction,
          () => instruction.usedBy.every(isDeadUse),
        );
  }

  bool isTrivialDeadStore(HInstruction instruction) {
    return instruction is HFieldSet &&
        isTrivialDeadStoreReceiver(instruction.getDartReceiver(closedWorld));
  }

  bool isDeadCode(HInstruction instruction) {
    if (instruction.usedBy.isNotEmpty) return false;
    if (isTrivialDeadStore(instruction)) return true;
    if (instruction.sideEffects.hasSideEffects()) return false;
    if (instruction.canThrow(_abstractValueDomain)) {
      if (canFoldIntoFollowingInstruction(instruction)) {
        // TODO(35996): If we remove [instruction], the source location of the
        // 'equivalent' instruction should be updated.
        return true;
      }
      return false;
    }
    if (instruction is HParameterValue) return false;
    if (instruction is HLocalSet) return false;
    return true;
  }

  @override
  void visitGraph(HGraph graph) {
    _graph = graph;
    _computeLiveness();
    visitPostDominatorTree(graph);
  }

  void _computeLiveness() {
    var analyzer = SsaLiveBlockAnalyzer(_graph, closedWorld, optimizer);
    analyzer.analyze();
    for (HBasicBlock block in _graph.blocks) {
      block.isLive = analyzer.isLiveBlock(block);
    }
  }

  @override
  bool validPostcondition(HGraph graph) {
    return NoUnusedPhiValidator.containsNoUnusedPhis(graph);
  }

  @override
  void visitBasicBlock(HBasicBlock block) {
    simplifyControlFlow(block);
    // Start from the last non-control flow instruction in the block.
    HInstruction? instruction = block.last!.previous;
    while (instruction != null) {
      var previous = instruction.previous;
      if (!block.isLive) {
        eliminatedSideEffects =
            eliminatedSideEffects || instruction.sideEffects.hasSideEffects();
        removeUsers(instruction);
        block.remove(instruction);
      } else if (isDeadCode(instruction)) {
        block.remove(instruction);
      }
      instruction = previous;
    }
    block.forEachPhi(simplifyPhi);
    evacuateTakenBranch(block);
    updateEmptyRegions(block);
  }

  void simplifyPhi(HPhi phi) {
    // Remove an unused HPhi so that the inputs can become potentially dead.
    if (!phi.block!.isLive) {
      removeUsers(phi);
    }

    if (phi.usedBy.isEmpty) {
      phi.block!.removePhi(phi);
      return;
    }

    // Run through the phis of the block and replace them with their input that
    // comes from the only live predecessor if that dominates the phi.
    //
    // TODO(sra): If the input is directly in the only live predecessor, it
    // might be possible to move it into [block] (e.g. all its inputs are
    // dominating.)
    // Find the index of the single live predecessor if it exists.
    List<HBasicBlock> predecessors = phi.block!.predecessors;
    int indexOfLive = -1;
    for (int i = 0; i < predecessors.length; i++) {
      if (predecessors[i].isLive) {
        if (indexOfLive >= 0) {
          indexOfLive = -1;
          break;
        }
        indexOfLive = i;
      }
    }

    if (indexOfLive >= 0) {
      HInstruction replacement = phi.inputs[indexOfLive];
      if (replacement.dominates(phi)) {
        final phiBlock = phi.block!;
        phiBlock.rewrite(phi, replacement);
        phiBlock.removePhi(phi);
        if (replacement.sourceElement == null &&
            phi.sourceElement != null &&
            replacement is! HThis) {
          replacement.sourceElement = phi.sourceElement;
        }
        return;
      }
    }

    // If the phi is of the form `phi(x, HTypeKnown(x))`, it does not strengthen
    // `x`.  We can replace the phi with `x` to potentially make the HTypeKnown
    // refinement node dead and potentially make a HIf control no HPhis.

    // TODO(sra): Implement version of this test that works for a subgraph of
    // HPhi nodes.
    HInstruction? base;
    bool seenUnrefinedBase = false;
    for (HInstruction input in phi.inputs) {
      HInstruction value = input;
      while (value is HTypeKnown) {
        HTypeKnown refinement = value;
        value = refinement.checkedInput;
      }
      if (value == input) seenUnrefinedBase = true;
      base ??= value;
      if (base != value) return;
    }

    if (seenUnrefinedBase) {
      final block = phi.block!;
      block.rewrite(phi, base!);
      block.removePhi(phi);
    }
  }

  void simplifyControlFlow(HBasicBlock block) {
    HInstruction? instruction = block.last;
    if (instruction is HIf) {
      HInstruction condition = instruction.condition;
      if (condition is HConstant) return;

      // We want to remove an if-then-else diamond when the then- and else-
      // branches are empty and the condition does not control a HPhi. We cannot
      // change the CFG structure so we replace the HIf condition with a
      // constant. This may leave the original condition unused and a candidate
      // for being dead code.
      //
      // TODO(http://dartbug.com/29475): Remove empty blocks so that recognizing
      // no-op control flow is trivial.

      final thenBlock = block.successors[0];
      final (thenContinuation, thenSize) = _emptyRegion[thenBlock]!;

      final elseBlock = block.successors[1];
      final (elseContinuation, elseSize) = _emptyRegion[elseBlock]!;

      if (thenContinuation != elseContinuation) return;
      if (!thenContinuation.phis.isEmpty) return;

      // Pick the 'live' branch to be the smallest subgraph.
      bool value = thenSize <= elseSize;
      HInstruction newCondition = _graph.addConstantBool(value, closedWorld);
      instruction.replaceInput(0, newCondition);
    }
  }

  /// Map from block to the continuation, and, if all paths to the continuation
  /// are empty, the number of blocks in that region. The block is either (1)
  /// the continuation of the block (a join point of a single-entry, single-exit
  /// region) or (2a) an earlier block if some the path to the continuation is
  /// not empty, or (2b) there is path that avoids the continuation (like a loop
  /// exit or a return). A block `B` that is non-empty has the entry `(B, 0)`. A
  /// block that dominates a region that has an exit or a path that is non-empty
  /// is also marked as `(B, 0)`.
  final Map<HBasicBlock, (HBasicBlock, int)> _emptyRegion = {};

  void updateEmptyRegions(HBasicBlock block) {
    // Default is to consider this block to be the entry to an non-empty region.
    _emptyRegion[block] = (block, 0);

    // To be empty, this block should have nothing except a single terminating
    // HControlFlow instruction.
    final instruction = block.first;
    if (instruction == null || instruction.next != null) return;
    if (!block.phis.isEmpty) return;

    if (!(instruction is HGoto ||
        instruction is HIf ||
        instruction is HBreak ||
        instruction is HSwitch)) {
      // Other control flow instructions either generate code (e.g. HReturn),
      // or are part of some structure like a loop or try-catch.
      return;
    }

    // If all paths from this block reach the same continuation, we have an
    // empty single-entry / single-exit region.  Create a new empty interval
    // from this block to the continuation, and extend it to the continuation of
    // the continuation.

    if (block.successors.isEmpty) return;

    int size = 1; // Size of empty region includes this block.

    HBasicBlock? continuation;
    if (block.successors.length == 1) {
      continuation = block.successors.single;
    } else {
      for (final successor in block.successors) {
        if (successor.id < block.id) return; // Back-edge
        final (successorContinuation, successorSize) = _emptyRegion[successor]!;
        size += successorSize;
        if (continuation == null) {
          continuation = successorContinuation;
        } else if (continuation != successorContinuation) {
          // This happens when (1) some successor is not empty, (2) some
          // successor is, or contains, an edge that exits the nested
          // forward-edge single-entry-single-exit regions.
          return;
        }
      }
    }

    if (continuation!.dominator == block) {
      final int continuationSize;
      (continuation, continuationSize) = _emptyRegion[continuation]!;
      size += continuationSize;
    }

    _emptyRegion[block] = (continuation, size);
  }

  /// If [block] is an always-taken branch, move the code from the taken branch
  /// into [block]. This has the effect of making the instructions available for
  /// further optimizations by moving them to a position that dominates the join
  /// point of the if-then-else.
  // TODO(29475): Delete dead blocks instead.
  void evacuateTakenBranch(HBasicBlock block) {
    if (!block.isLive) return;
    HInstruction? branch = block.last;
    if (branch is HIf) {
      if (branch.thenBlock.isLive == branch.elseBlock.isLive) return;
      assert(branch.condition is HConstant);
      HBasicBlock liveSuccessor = branch.thenBlock.isLive
          ? branch.thenBlock
          : branch.elseBlock;
      HInstruction instruction = liveSuccessor.first!;
      // Move instructions up until the final control flow instruction or pinned
      // HTypeKnown.
      while (instruction.next != null) {
        if (instruction is HTypeKnown && instruction.isPinned) break;
        HInstruction next = instruction.next!;
        // It might be worth re-running GVN optimizations if we hoisted a
        // GVN-able instructions from [target] into [block].
        newGvnCandidates = newGvnCandidates || instruction.useGvn();
        instruction.block!.detach(instruction);
        block.moveAtExit(instruction);
        instruction = next;
      }
    }
  }

  void removeUsers(HInstruction instruction) {
    for (var user in instruction.usedBy) {
      removeInput(user, instruction);
    }
    instruction.usedBy.clear();
  }

  void removeInput(HInstruction user, HInstruction input) {
    List<HInstruction> inputs = user.inputs;
    for (int i = 0, length = inputs.length; i < length; i++) {
      if (input == inputs[i]) {
        user.inputs[i] = zapInstruction;
        zapInstruction.usedBy.add(user);
      }
    }
  }
}

class SsaLiveBlockAnalyzer extends HBaseVisitor<void> {
  final HGraph graph;
  final Set<HBasicBlock> live = {};
  final List<HBasicBlock> worklist = [];
  final SsaOptimizerTask optimizer;
  final JClosedWorld closedWorld;

  SsaLiveBlockAnalyzer(this.graph, this.closedWorld, this.optimizer);

  AbstractValueDomain get _abstractValueDomain =>
      closedWorld.abstractValueDomain;

  Map<HInstruction, Range> get ranges => optimizer.ranges;

  bool isLiveBlock(HBasicBlock block) => live.contains(block);

  void analyze() {
    markBlockLive(graph.entry);
    while (worklist.isNotEmpty) {
      HBasicBlock live = worklist.removeLast();
      live.last!.accept(this);
    }
  }

  void markBlockLive(HBasicBlock block) {
    if (!live.contains(block)) {
      worklist.add(block);
      live.add(block);
    }
  }

  @override
  void visitControlFlow(HControlFlow node) {
    node.block!.successors.forEach(markBlockLive);
  }

  @override
  void visitIf(HIf node) {
    HInstruction condition = node.condition;
    if (condition is HConstant) {
      if (condition.isConstantTrue()) {
        markBlockLive(node.thenBlock);
      } else {
        markBlockLive(node.elseBlock);
      }
    } else {
      visitControlFlow(node);
    }
  }

  @override
  void visitSwitch(HSwitch node) {
    if (node.expression.isInteger(_abstractValueDomain).isDefinitelyTrue) {
      final switchRange = ranges[node.expression];
      if (switchRange != null) {
        final lowerValue = switchRange.lower;
        final upperValue = switchRange.upper;
        if (lowerValue is IntValue && upperValue is IntValue) {
          BigInt lower = lowerValue.value;
          BigInt upper = upperValue.value;
          Set<BigInt> liveLabels = {};
          for (int pos = 1; pos < node.inputs.length; pos++) {
            HConstant input = node.inputs[pos] as HConstant;
            final constant = input.constant;
            if (constant is! IntConstantValue) {
              // The switch expression is an integer but the constant is not, so
              // the target block is unreachable.
              continue;
            }
            BigInt label = constant.intValue;
            if (!liveLabels.contains(label) &&
                label <= upper &&
                label >= lower) {
              markBlockLive(node.block!.successors[pos - 1]);
              liveLabels.add(label);
            }
          }
          if (BigInt.from(liveLabels.length) != upper - lower + BigInt.one) {
            markBlockLive(node.defaultTarget);
          }
          return;
        }
      }
    }
    visitControlFlow(node);
  }
}

class SsaDeadPhiEliminator implements OptimizationPhase {
  @override
  final String name = "SsaDeadPhiEliminator";

  @override
  void visitGraph(HGraph graph) {
    final List<HPhi> worklist = [];
    // A set to keep track of the live phis that we found.
    final Set<HPhi> livePhis = {};

    // Add to the worklist all live phis: phis referenced by non-phi
    // instructions.
    for (final block in graph.blocks) {
      block.forEachPhi((HPhi phi) {
        for (final user in phi.usedBy) {
          if (user is! HPhi) {
            worklist.add(phi);
            livePhis.add(phi);
            break;
          }
        }
      });
    }

    // Process the worklist by propagating liveness to phi inputs.
    while (worklist.isNotEmpty) {
      HPhi phi = worklist.removeLast();
      for (final input in phi.inputs) {
        if (input is HPhi && !livePhis.contains(input)) {
          worklist.add(input);
          livePhis.add(input);
        }
      }
    }

    // Collect dead phis.
    List<HPhi> deadPhis = [];
    for (final block in graph.blocks) {
      block.forEachPhi((phi) {
        if (!livePhis.contains(phi)) deadPhis.add(phi);
      });
    }

    // Two-phase removal, phase 1: unlink all the input nodes.
    for (final phi in deadPhis) {
      for (final input in phi.inputs) {
        input.removeUser(phi);
      }
      phi.inputs.clear();
    }

    // Two-phase removal, phase 2: remove the now-disconnected phis.
    for (final phi in deadPhis) {
      assert(phi.inputs.isEmpty);
      assert(phi.usedBy.isEmpty);
      phi.block!.removePhi(phi);
    }
  }

  @override
  bool validPostcondition(HGraph graph) {
    return NoUnusedPhiValidator.containsNoUnusedPhis(graph);
  }
}

class SsaRedundantPhiEliminator implements OptimizationPhase {
  @override
  final String name = "SsaRedundantPhiEliminator";

  @override
  void visitGraph(HGraph graph) {
    final List<HPhi> worklist = [];

    // Add all phis in the worklist.
    for (final block in graph.blocks) {
      block.forEachPhi((HPhi phi) => worklist.add(phi));
    }

    while (worklist.isNotEmpty) {
      HPhi phi = worklist.removeLast();

      // If the phi has already been processed, continue.
      if (!phi.isInBasicBlock()) continue;

      // Find if the inputs of the phi are the same instruction.
      // The builder ensures that phi.inputs[0] cannot be the phi
      // itself.
      assert(!identical(phi.inputs[0], phi));
      HInstruction? candidate = phi.inputs[0];
      for (int i = 1; i < phi.inputs.length; i++) {
        HInstruction input = phi.inputs[i];
        // If the input is the phi, the phi is still candidate for
        // elimination.
        if (!identical(input, candidate) && !identical(input, phi)) {
          candidate = null;
          break;
        }
      }

      // If the inputs are not the same, continue.
      if (candidate == null) continue;

      // Because we're updating the users of this phi, we may have new
      // phis candidate for elimination. Add phis that used this phi
      // to the worklist.
      for (final user in phi.usedBy) {
        if (user is HPhi) worklist.add(user);
      }
      final phiBlock = phi.block!;
      phiBlock.rewrite(phi, candidate);
      phiBlock.removePhi(phi);
      if (candidate.sourceElement == null &&
          phi.sourceElement != null &&
          candidate is! HThis) {
        candidate.sourceElement = phi.sourceElement;
      }
    }
  }

  @override
  bool validPostcondition(HGraph graph) => true;
}

class GvnWorkItem {
  final HBasicBlock block;
  final ValueSet valueSet;
  GvnWorkItem(this.block, this.valueSet);
}

class SsaGlobalValueNumberer implements OptimizationPhase {
  final AbstractValueDomain _abstractValueDomain;
  @override
  final String name = "SsaGlobalValueNumberer";
  final Set<int> visited = {};

  late final List<Bitset> blockChangesFlags;
  late final List<Bitset> loopChangesFlags;

  SsaGlobalValueNumberer(this._abstractValueDomain);

  @override
  void visitGraph(HGraph graph) {
    computeChangesFlags(graph);
    moveLoopInvariantCode(graph);
    List<GvnWorkItem> workQueue = [GvnWorkItem(graph.entry, ValueSet())];
    do {
      GvnWorkItem item = workQueue.removeLast();
      visitBasicBlock(item.block, item.valueSet, workQueue);
    } while (workQueue.isNotEmpty);
  }

  @override
  bool validPostcondition(HGraph graph) => true;

  void moveLoopInvariantCode(HGraph graph) {
    for (int i = graph.blocks.length - 1; i >= 0; i--) {
      HBasicBlock block = graph.blocks[i];
      if (block.isLoopHeader()) {
        final changesFlags = loopChangesFlags[block.id];
        final info = block.loopInformation!;
        // Iterate over all blocks of this loop. Note that blocks in
        // inner loops are not visited here, but we know they
        // were visited before because we are iterating in post-order.
        // So instructions that are GVN'ed in an inner loop are in their
        // loop entry, and [info.blocks] contains this loop entry.
        moveLoopInvariantCodeFromBlock(block, block, changesFlags);
        for (HBasicBlock other in info.blocks) {
          moveLoopInvariantCodeFromBlock(other, block, changesFlags);
        }
      }
    }
  }

  void moveLoopInvariantCodeFromBlock(
    HBasicBlock block,
    HBasicBlock loopHeader,
    Bitset changesFlags,
  ) {
    assert(block.parentLoopHeader == loopHeader || block == loopHeader);
    HBasicBlock preheader = loopHeader.predecessors[0];
    var dependsFlags = SideEffects.computeDependsOnFlags(changesFlags);
    HInstruction? instruction = block.first;
    bool isLoopAlwaysTaken() {
      final instruction = loopHeader.last!;
      assert(instruction is HGoto || instruction is HLoopBranch);
      return instruction is HGoto || instruction.inputs[0].isConstantTrue();
    }

    bool firstInstructionInLoop =
        block == loopHeader
        // Compensate for lack of code motion.
        ||
        (blockChangesFlags[loopHeader.id].isEmpty &&
            isLoopAlwaysTaken() &&
            loopHeader.successors[0] == block);
    while (instruction != null) {
      final next = instruction.next;
      if (instruction.useGvn() &&
          instruction.isMovable &&
          (!instruction.canThrow(_abstractValueDomain) ||
              firstInstructionInLoop) &&
          !instruction.sideEffects.dependsOn(dependsFlags)) {
        bool loopInvariantInputs = true;
        List<HInstruction> inputs = instruction.inputs;
        for (int i = 0, length = inputs.length; i < length; i++) {
          if (isInputDefinedAfterDominator(inputs[i], preheader)) {
            loopInvariantInputs = false;
            break;
          }
        }

        // If the inputs are loop invariant, we can move the
        // instruction from the current block to the pre-header block.
        if (loopInvariantInputs) {
          block.detach(instruction);
          preheader.moveAtExit(instruction);
        } else {
          firstInstructionInLoop = false;
        }
      }
      final oldChangesFlags = changesFlags;
      changesFlags = changesFlags.union(
        instruction.sideEffects.getChangesFlags(),
      );
      if (oldChangesFlags != changesFlags) {
        dependsFlags = SideEffects.computeDependsOnFlags(changesFlags);
      }
      instruction = next;
    }
  }

  bool isInputDefinedAfterDominator(HInstruction input, HBasicBlock dominator) {
    return input.block!.id > dominator.id;
  }

  void visitBasicBlock(
    HBasicBlock block,
    ValueSet values,
    List<GvnWorkItem> workQueue,
  ) {
    HInstruction? instruction = block.first;
    if (block.isLoopHeader()) {
      final flags = loopChangesFlags[block.id];
      values.kill(flags);
    }
    while (instruction != null) {
      final next = instruction.next;
      final flags = instruction.sideEffects.getChangesFlags();
      assert(flags.isEmpty || !instruction.useGvn());
      // TODO(sra): Is the above assertion too strong? We should be able to
      // reuse the values generated by idempotent operations that have
      // effects. Would it be correct to make the kill below be conditional on
      // not replacing the instruction?
      values.kill(flags);
      if (instruction.useGvn()) {
        final other = values.lookup(instruction);
        if (other != null) {
          assert(other.gvnEquals(instruction) && instruction.gvnEquals(other));
          block.rewriteWithBetterUser(instruction, other);
          block.remove(instruction);
        } else {
          values.add(instruction);
        }
      }
      instruction = next;
    }

    List<HBasicBlock> dominatedBlocks = block.dominatedBlocks;
    for (int i = 0, length = dominatedBlocks.length; i < length; i++) {
      HBasicBlock dominated = dominatedBlocks[i];
      // No need to copy the value set for the last child.
      ValueSet successorValues = (i == length - 1) ? values : values.copy();
      // If we have no values in our set, we do not have to kill
      // anything. Also, if the range of block ids from the current
      // block to the dominated block is empty, there is no blocks on
      // any path from the current block to the dominated block so we
      // don't have to do anything either.
      assert(block.id < dominated.id);
      if (!successorValues.isEmpty && block.id + 1 < dominated.id) {
        visited.clear();
        List<HBasicBlock> workQueue = <HBasicBlock>[dominated];
        var changesFlags = Bitset.empty();
        do {
          HBasicBlock current = workQueue.removeLast();
          changesFlags = changesFlags.union(
            getChangesFlagsForDominatedBlock(block, current, workQueue),
          );
        } while (workQueue.isNotEmpty);
        successorValues.kill(changesFlags);
      }
      workQueue.add(GvnWorkItem(dominated, successorValues));
    }
  }

  void computeChangesFlags(HGraph graph) {
    // Create the changes flags lists. Make sure to initialize the
    // loop changes flags list to zero so we can use bitwise-or when
    // propagating loop changes upwards.
    final int length = graph.blocks.length;
    blockChangesFlags = List<Bitset>.filled(length, SideEffects.allChanges);
    loopChangesFlags = List<Bitset>.filled(length, Bitset.empty());

    // Run through all the basic blocks in the graph and fill in the
    // changes flags lists.
    for (int i = length - 1; i >= 0; i--) {
      final HBasicBlock block = graph.blocks[i];
      final int id = block.id;

      // Compute block changes flags for the block.
      var changesFlags = Bitset.empty();
      HInstruction? instruction = block.first;
      while (instruction != null) {
        changesFlags = changesFlags.union(
          instruction.sideEffects.getChangesFlags(),
        );
        instruction = instruction.next;
      }
      assert(blockChangesFlags[id] == SideEffects.allChanges);
      blockChangesFlags[id] = changesFlags;

      // Loop headers are part of their loop, so update the loop
      // changes flags accordingly.
      if (block.isLoopHeader()) {
        loopChangesFlags[id] = loopChangesFlags[id].union(changesFlags);
      }

      // Propagate loop changes flags upwards.
      final parentLoopHeader = block.parentLoopHeader;
      if (parentLoopHeader != null) {
        loopChangesFlags[parentLoopHeader.id] =
            loopChangesFlags[parentLoopHeader.id].union(
              (block.isLoopHeader()) ? loopChangesFlags[id] : changesFlags,
            );
      }
    }
  }

  Bitset getChangesFlagsForDominatedBlock(
    HBasicBlock dominator,
    HBasicBlock dominated,
    List<HBasicBlock> workQueue,
  ) {
    var changesFlags = Bitset.empty();
    List<HBasicBlock> predecessors = dominated.predecessors;
    for (int i = 0, length = predecessors.length; i < length; i++) {
      HBasicBlock block = predecessors[i];
      int id = block.id;
      // If the current predecessor block is on the path from the
      // dominator to the dominated, it must have an id that is in the
      // range from the dominator to the dominated.
      if (dominator.id < id && id < dominated.id && !visited.contains(id)) {
        visited.add(id);
        changesFlags = changesFlags.union(blockChangesFlags[id]);
        // Loop bodies might not be on the path from dominator to dominated,
        // but they can invalidate values.
        changesFlags = changesFlags.union(loopChangesFlags[id]);
        workQueue.add(block);
      }
    }
    return changesFlags;
  }
}

// This phase merges equivalent instructions on different paths into
// one instruction in a dominator block. It runs through the graph
// post dominator order and computes a ValueSet for each block of
// instructions that can be moved to a dominator block. These
// instructions are the ones that:
// 1) can be used for GVN, and
// 2) do not use definitions of their own block.
//
// A basic block looks at its successors and finds the intersection of
// these computed ValueSet. It moves all instructions of the
// intersection into its own list of instructions.
class SsaCodeMotion extends HBaseVisitor<void> implements OptimizationPhase {
  final AbstractValueDomain _abstractValueDomain;

  @override
  final String name = "SsaCodeMotion";

  bool movedCode = false;
  late final List<ValueSet> values;

  SsaCodeMotion(this._abstractValueDomain);

  @override
  void visitGraph(HGraph graph) {
    values = List.generate(graph.blocks.length, (_) => ValueSet());
    visitPostDominatorTree(graph);
  }

  @override
  bool validPostcondition(HGraph graph) => true;

  @override
  void visitBasicBlock(HBasicBlock node) {
    List<HBasicBlock> successors = node.successors;

    // Phase 1: get the ValueSet of all successors (if there are more than one),
    // compute the intersection and move the instructions of the intersection
    // into this block.
    if (successors.length > 1) {
      ValueSet instructions = values[successors[0].id];
      for (int i = 1; i < successors.length; i++) {
        ValueSet other = values[successors[i].id];
        instructions = instructions.intersection(other);
      }

      if (!instructions.isEmpty) {
        List<HInstruction> list = instructions.toList();
        // Sort by instruction 'id' for more stable ordering under changes to
        // unrelated source code. 'id' is a function of the operations of
        // compiling the current method, whereas the ValueSet order is dependent
        // hashCodes that are a function of the whole program.
        list.sort((insn1, insn2) => insn1.id.compareTo(insn2.id));
        for (HInstruction instruction in list) {
          // Move the instruction to the current block.
          instruction.block!.detach(instruction);
          node.moveAtExit(instruction);
          // Go through all successors and rewrite their instruction
          // to the shared one.
          for (final successor in successors) {
            final toRewrite = values[successor.id].lookup(instruction);
            if (toRewrite != instruction) {
              successor.rewriteWithBetterUser(toRewrite, instruction);
              successor.remove(toRewrite!);
              movedCode = true;
            }
          }
        }
      }
      // TODO(sra): There are some non-gvn-able instructions that we could move,
      // e.g. allocations. We should probably not move instructions that can
      // directly or indirectly throw since the reported location might be in
      // the 'wrong' branch.
    }

    // Don't try to merge instructions to a dominator if we have
    // multiple predecessors.
    if (node.predecessors.length != 1) return;

    // Phase 2: Go through all instructions of this block and find
    // which instructions can be moved to a dominator block.
    ValueSet set_ = values[node.id];
    HInstruction? instruction = node.first;
    var flags = Bitset.empty();
    while (instruction != null) {
      final dependsFlags = SideEffects.computeDependsOnFlags(flags);
      flags = flags.union(instruction.sideEffects.getChangesFlags());

      HInstruction current = instruction;
      instruction = instruction.next;
      if (!current.useGvn() || !current.isMovable) continue;
      // TODO(sra): We could move throwing instructions provided we keep the
      // exceptions in the same order.  This requires they are in the same order
      // in all successors, which is not tracked by the ValueSet.
      if (current.canThrow(_abstractValueDomain)) continue;
      if (current.sideEffects.dependsOn(dependsFlags)) continue;

      bool canBeMoved = true;
      for (final HInstruction input in current.inputs) {
        if (input.block == node) {
          canBeMoved = false;
          break;
          // TODO(sra): We could move trees of instructions provided we move the
          // roots before the leaves.
        }
      }
      if (!canBeMoved) continue;

      final existing = set_.lookup(current);
      if (existing == null) {
        set_.add(current);
      } else {
        node.rewriteWithBetterUser(current, existing);
        node.remove(current);
        movedCode = true;
      }
    }
  }
}

class SsaTypeConversionInserter extends HBaseVisitor<void>
    implements OptimizationPhase {
  @override
  final String name = "SsaTypeconversionInserter";
  final JClosedWorld closedWorld;

  SsaTypeConversionInserter(this.closedWorld);

  AbstractValueDomain get _abstractValueDomain =>
      closedWorld.abstractValueDomain;

  @override
  void visitGraph(HGraph graph) {
    visitDominatorTree(graph);
  }

  @override
  bool validPostcondition(HGraph graph) => true;

  // Update users of [input] that are dominated by [:dominator.first:]
  // to use [TypeKnown] of [input] instead. As the type information depends
  // on the control flow, we mark the inserted [HTypeKnown] nodes as
  // non-movable.
  void insertTypePropagationForDominatedUsers(
    HBasicBlock dominator,
    HInstruction input,
    AbstractValue convertedType,
  ) {
    DominatedUses dominatedUses = DominatedUses.of(input, dominator.first!);
    if (dominatedUses.isEmpty) return;

    // Check to avoid adding a duplicate HTypeKnown node.
    if (dominatedUses.isSingleton) {
      HInstruction user = dominatedUses.single;
      if (user is HTypeKnown &&
          user.isPinned &&
          user.knownType == convertedType &&
          user.checkedInput == input) {
        return;
      }
    }

    HTypeKnown newInput = HTypeKnown.pinned(convertedType, input);
    dominator.addBefore(dominator.first, newInput);
    dominatedUses.replaceWith(newInput);
  }

  @override
  void visitIsTest(HIsTest node) {
    List<HBasicBlock> trueTargets = [];
    List<HBasicBlock> falseTargets = [];

    collectTargets(node, trueTargets, falseTargets);

    if (trueTargets.isEmpty && falseTargets.isEmpty) return;

    AbstractValue convertedType = node.checkedAbstractValue.abstractValue;
    HInstruction input = node.checkedInput;

    for (HBasicBlock block in trueTargets) {
      insertTypePropagationForDominatedUsers(block, input, convertedType);
    }
    // TODO(sra): Also strengthen uses for when the condition is precise and
    // known false (e.g. int? x; ... if (x is! int) use(x)). Avoid strengthening
    // to `null`.
  }

  @override
  void visitIsTestSimple(HIsTestSimple node) {
    List<HBasicBlock> trueTargets = [];
    List<HBasicBlock> falseTargets = [];

    collectTargets(node, trueTargets, falseTargets);

    if (trueTargets.isEmpty && falseTargets.isEmpty) return;

    AbstractValue convertedType = node.checkedAbstractValue.abstractValue;
    HInstruction input = node.checkedInput;

    for (HBasicBlock block in trueTargets) {
      insertTypePropagationForDominatedUsers(block, input, convertedType);
    }
    // TODO(sra): Also strengthen uses for when the condition is precise and
    // known false (e.g. int? x; ... if (x is! int) use(x)). Avoid strengthening
    // to `null`.
  }

  @override
  void visitIdentity(HIdentity node) {
    // At HIf(HIdentity(x, null)) strengthens x to non-null on else branch.
    HInstruction left = node.left;
    HInstruction right = node.right;
    HInstruction input;

    if (left.isConstantNull()) {
      input = right;
    } else if (right.isConstantNull()) {
      input = left;
    } else {
      return;
    }

    if (_abstractValueDomain.isNull(input.instructionType).isDefinitelyFalse) {
      return;
    }

    List<HBasicBlock> trueTargets = [];
    List<HBasicBlock> falseTargets = [];

    collectTargets(node, trueTargets, falseTargets);

    if (trueTargets.isEmpty && falseTargets.isEmpty) return;

    AbstractValue nonNullType = _abstractValueDomain.excludeNull(
      input.instructionType,
    );

    for (HBasicBlock block in falseTargets) {
      insertTypePropagationForDominatedUsers(block, input, nonNullType);
    }
    // We don't strengthen the known-true references. It doesn't happen often
    // and we don't want "if (x==null) return x;" to convert between JavaScript
    // 'null' and 'undefined'.
  }

  void collectTargets(
    HInstruction instruction,
    List<HBasicBlock>? trueTargets,
    List<HBasicBlock>? falseTargets,
  ) {
    if (trueTargets == null && falseTargets == null) return;

    for (HInstruction user in instruction.usedBy) {
      if (user is HIf) {
        trueTargets?.add(user.thenBlock);
        falseTargets?.add(user.elseBlock);

        final joinBlock = user.joinBlock;
        if (joinBlock != null) {
          final joinPredecessors = joinBlock.predecessors;
          if (joinPredecessors.length == 2) {
            if (hasUnreachableExit(joinPredecessors[0])) {
              // The then-branch does not reach the join block, so the join
              // block is reached only if condition is false.
              falseTargets?.add(joinBlock);
            } else if (hasUnreachableExit(joinPredecessors[1])) {
              // The else-branch does not reach the join block, so the join
              // block is reached only if condition is true.
              trueTargets?.add(joinBlock);
            } else {
              final phi = joinBlock.phis.firstPhi;
              if (phi != null && phi.next == null) {
                assert(phi.inputs.length == 2);

                // This is a single phi controlled by `user`.
                //
                // Collect the targets of the phi. The phi is in effectively a
                // conditional `user ? left : right`.

                final right = phi.inputs[1];
                if (right.isConstantFalse()) {
                  // When `c ? x : false` is true, `c` must be true.
                  // So pass `c`'s trueTargets as the phi's trueTargets.
                  collectTargets(phi, trueTargets, null);
                } else if (right.isConstantTrue()) {
                  // When `c ? x : true` is false, `c` must be true.
                  // So pass `c`'s trueTargets as the phi's falseTargets.
                  collectTargets(phi, null, trueTargets);
                }

                final left = phi.inputs[0];
                if (left.isConstantFalse()) {
                  // When `c ? false : x` is true, `c` must be false.
                  // So pass `c`'s falseTargets as the phi's trueTargets.
                  collectTargets(phi, falseTargets, null);
                } else if (left.isConstantTrue()) {
                  // When `c ? true : x` is false, `c` must be false.
                  // So pass `c`'s falseTargets as the phi's falseTargets.
                  collectTargets(phi, null, falseTargets);
                }

                // Sanity checks:
                //
                // For `c ? true : false`, we pass both `c`'s trueTargets and
                // falseTargets as the same targets of the phi.
                //
                // For `c ? false : true`, we pass the targets reversed, like we
                // for `HNot`.
                //
                // For `c ? false : false`, we pass both `c`'s trueTargets and
                // falseTargets to the unreachable trueTargets of the phi. We
                // might insert contradictory strengthenings, which might refine
                // a value to Never, i.e. we potentially 'prove' the code is
                // unreachable.
              }
            }
          }
        }
      } else if (user is HLoopBranch) {
        trueTargets?.add(user.block!.successors.first);
        // Don't insert refinements on else-branch - may be a critical edge
        // block which we currently need to keep empty (except for phis).
      } else if (user is HNot) {
        collectTargets(user, falseTargets, trueTargets);
      } else if (user is HPhi) {
        List<HInstruction> inputs = user.inputs;
        if (inputs.length == 2) {
          assert(inputs.contains(instruction));
          HInstruction other = inputs[(inputs[0] == instruction) ? 1 : 0];
          if (other.isConstantTrue()) {
            // The condition flows to `HPhi(true, user)` or `HPhi(user, true)`,
            // which means that a downstream HIf has true-branch control flow
            // that does not depend on the original instruction, so stop
            // collecting [trueTargets].
            collectTargets(user, null, falseTargets);
          } else if (other.isConstantFalse()) {
            // Ditto for false.
            collectTargets(user, trueTargets, null);
          }
        }
      }
    }
  }
}

/// Optimization phase that tries to eliminate memory loads (for example
/// [HFieldGet]), when it knows the value stored in that memory location, and
/// stores that overwrite with the same value.
class SsaLoadElimination extends HBaseVisitor<void>
    implements OptimizationPhase {
  final JClosedWorld _closedWorld;
  final JFieldAnalysis _fieldAnalysis;
  @override
  final String name = "SsaLoadElimination";
  late MemorySet memorySet;
  late final List<MemorySet?> memories;
  bool newGvnCandidates = false;
  late final HGraph _graph;

  // Blocks that can be reached via control flow not expressed by the basic
  // block CFG. These are catch and finally blocks that are reached from some
  // mid-block instruction that throws in the CFG region corresponding to the
  // Dart language try-block. The value stored in the map is the HTry that owns
  // the catch or finally block. This map is filled in on-the-fly since the HTry
  // dominates the catch and finally so is visited first.
  Map<HBasicBlock, HTry>? _blocksWithImprecisePredecessors;

  SsaLoadElimination(this._closedWorld)
    : _fieldAnalysis = _closedWorld.fieldAnalysis;

  AbstractValueDomain get _abstractValueDomain =>
      _closedWorld.abstractValueDomain;

  @override
  void visitGraph(HGraph graph) {
    _graph = graph;
    memories = List<MemorySet?>.filled(graph.blocks.length, null);
    List<HBasicBlock> blocks = graph.blocks;
    for (int i = 0; i < blocks.length; i++) {
      HBasicBlock block = blocks[i];
      visitBasicBlock(block);
      if (block.successors.isNotEmpty && block.successors[0].isLoopHeader()) {
        // We've reached the ending block of a loop. Iterate over the
        // blocks of the loop again to take values that flow from that
        // ending block into account.
        for (int j = block.successors[0].id; j <= block.id; j++) {
          visitBasicBlock(blocks[j]);
        }
      }
    }
  }

  @override
  bool validPostcondition(HGraph graph) => true;

  @override
  void visitBasicBlock(HBasicBlock node) {
    final predecessors = node.predecessors;
    final indegree = predecessors.length;
    if (indegree == 0) {
      // Entry block.
      memorySet = MemorySet(_closedWorld);
    } else if (indegree == 1 && predecessors[0].successors.length == 1) {
      // No need to clone, there is no other successor for
      // `block.predecessors[0]`, and this block has only one predecessor. Since
      // we are not going to visit `block.predecessors[0]` again, we can just
      // re-use its [memorySet].
      memorySet = memories[predecessors[0].id]!;
    } else if (indegree == 1) {
      // Clone the memorySet of the predecessor, because it is also used by
      // other successors of it.
      memorySet = memories[predecessors[0].id]!.clone();
    } else {
      // Compute the intersection of all predecessors.
      //
      // If a predecessor does not have a reachable exit, the kills on that path
      // can be ignored. Since the usual case is conditional diamond flow with
      // two predecessors, this is done by detecting a single non-dead
      // predecessor and cloning the memory-set, but removing expressions that
      // are not valid in the current block (invalid instructions would be in
      // one arm of the diamond).

      int firstLiveIndex = -1;
      int otherLiveIndex = -1;
      int firstDeadIndex = -1;
      bool pendingBackEdge = false;

      List<MemorySet?> inputs = List.filled(indegree, null);

      for (int i = 0; i < indegree; i++) {
        final predecessor = predecessors[i];
        final input = inputs[i] = memories[predecessor.id];
        if (input == null) pendingBackEdge = true;
        if (hasUnreachableExit(predecessor)) {
          if (firstDeadIndex == -1) firstDeadIndex = i;
        } else {
          if (firstLiveIndex == -1) {
            firstLiveIndex = i;
          } else if (otherLiveIndex == -1) {
            otherLiveIndex = i;
          }
        }
      }

      if (firstLiveIndex != -1 &&
          otherLiveIndex == -1 &&
          firstDeadIndex != -1 &&
          !pendingBackEdge) {
        // Single live input intersection.
        memorySet = memories[predecessors[firstLiveIndex].id]!
            .cloneIfDominatesBlock(node);
      } else {
        // Standard intersection over all predecessors.
        memorySet = inputs[0]!;
        for (int i = 1; i < inputs.length; i++) {
          memorySet = memorySet.intersectionFor(inputs[i], node, i);
        }
      }
    }

    // If the current block is a catch or finally block, it is reachable from
    // any instruction in the try region that can generate an exception.
    if (_blocksWithImprecisePredecessors != null) {
      final tryInstruction = _blocksWithImprecisePredecessors![node];
      if (tryInstruction != null) {
        memorySet.killLocationsForExceptionEdge();
      }
    }

    memories[node.id] = memorySet;
    HInstruction? instruction = node.first;
    while (instruction != null) {
      final next = instruction.next;
      instruction.accept(this);
      instruction = next;
    }
  }

  @override
  void visitTry(HTry node) {
    final impreciseBlocks = _blocksWithImprecisePredecessors ??= {};
    if (node.catchBlock != null) {
      impreciseBlocks[node.catchBlock!] = node;
    }
    if (node.finallyBlock != null) {
      impreciseBlocks[node.finallyBlock!] = node;
    }
  }

  void checkNewGvnCandidates(HInstruction instruction, HInstruction existing) {
    if (newGvnCandidates) return;
    bool hasUseGvn(HInstruction insn) => insn.nonCheck().useGvn();
    if (instruction.usedBy.any(hasUseGvn) && existing.usedBy.any(hasUseGvn)) {
      newGvnCandidates = true;
    }
  }

  @override
  void visitFieldGet(HFieldGet node) {
    FieldEntity element = node.element;
    HInstruction receiver = node.getDartReceiver(_closedWorld).nonCheck();
    _visitFieldGet(element, receiver, node);
  }

  @override
  void visitGetLength(HGetLength node) {
    HInstruction receiver = node.receiver.nonCheck();
    final existing = memorySet.lookupFieldValue(MemoryFeature.length, receiver);
    if (existing != null) {
      checkNewGvnCandidates(node, existing);
      final block = node.block!;
      block.rewriteWithBetterUser(node, existing);
      block.remove(node);
    } else {
      memorySet.registerFieldValue(MemoryFeature.length, receiver, node);
    }
  }

  void _visitFieldGet(
    FieldEntity element,
    HInstruction receiver,
    HInstruction instruction,
  ) {
    final existing = memorySet.lookupFieldValue(element, receiver);
    if (existing != null) {
      checkNewGvnCandidates(instruction, existing);
      final block = instruction.block!;
      block.rewriteWithBetterUser(instruction, existing);
      block.remove(instruction);
    } else {
      memorySet.registerFieldValue(element, receiver, instruction);
    }
  }

  @override
  void visitFieldSet(HFieldSet node) {
    FieldEntity element = node.element;
    HInstruction receiver = node.getDartReceiver(_closedWorld).nonCheck();
    if (memorySet.registerFieldValueUpdate(element, receiver, node.value)) {
      node.block!.remove(node);
    }
  }

  @override
  void visitCreate(HCreate node) {
    memorySet.registerAllocation(node);
    if (shouldTrackInitialValues(node)) {
      int argumentIndex = 0;
      _closedWorld.elementEnvironment.forEachInstanceField(node.element, (
        _,
        FieldEntity member,
      ) {
        FieldAnalysisData fieldData = _fieldAnalysis.getFieldData(member);
        if (fieldData.isElided) return;
        if (fieldData.isInitializedInAllocator) {
          // TODO(sra): Can we avoid calling HGraph.addConstant?
          final value = fieldData.initialValue!;
          HConstant constant = _graph.addConstant(value, _closedWorld);
          memorySet.registerFieldValue(member, node, constant);
        } else {
          memorySet.registerFieldValue(
            member,
            node,
            node.inputs[argumentIndex++],
          );
        }
      });
    }
    // In case this instruction has as input non-escaping objects, we
    // need to mark these objects as escaping.
    memorySet.killAffectedBy(node);
  }

  bool shouldTrackInitialValues(HCreate instruction) {
    // Don't track initial field values of an allocation that are
    // unprofitable. We search the chain of single uses in allocations for a
    // limited depth.

    const maxHeapDepth = 5;

    bool interestingUse(HInstruction instruction, int heapDepth) {
      // Heuristic: if the allocation is too deep in heap it is unlikely we will
      // recover a field by load-elimination.
      // TODO(sra): We can measure this depth by looking at load chains.
      if (heapDepth == maxHeapDepth) return false;
      // There are multiple uses so do the full store analysis.
      if (instruction.usedBy.length != 1) return true;
      HInstruction use = instruction.usedBy.single;
      // When the only use is an allocation, the allocation becomes the only
      // heap alias for the current instruction.
      if (use is HCreate) return interestingUse(use, heapDepth + 1);
      if (use is HLiteralList) return interestingUse(use, heapDepth + 1);
      if (use is HInvokeStatic) {
        // Assume the argument escapes. All we do with our initial allocation is
        // have it escape or store it into an object that escapes.
        return false;
        // TODO(sra): Handle library functions that we know do not modify or
        // leak the inputs. For example `setArrayType` is used to mark
        // list literals with type information.
      }
      if (use is HPhi) {
        // The initial allocation (it's only alias) gets merged out of the model
        // of the heap before load.
        return false;
      }
      return true;
    }

    return interestingUse(instruction, 0);
  }

  @override
  void visitInstruction(HInstruction instruction) {
    if (instruction.isAllocation(_abstractValueDomain)) {
      memorySet.registerAllocation(instruction);
    }
    memorySet.killAffectedBy(instruction);
  }

  @override
  void visitLazyStatic(HLazyStatic node) {
    FieldEntity field = node.element;
    handleStaticLoad(field, node);
  }

  void handleStaticLoad(MemberEntity element, HInstruction instruction) {
    final existing = memorySet.lookupFieldValue(element, null);
    if (existing != null) {
      checkNewGvnCandidates(instruction, existing);
      final block = instruction.block!;
      block.rewriteWithBetterUser(instruction, existing);
      block.remove(instruction);
    } else {
      memorySet.registerFieldValue(element, null, instruction);
    }
  }

  @override
  void visitStatic(HStatic node) {
    handleStaticLoad(node.element, node);
  }

  @override
  void visitStaticStore(HStaticStore node) {
    if (memorySet.registerFieldValueUpdate(
      node.element,
      null,
      node.inputs.last,
    )) {
      node.block!.remove(node);
    }
  }

  @override
  void visitLiteralList(HLiteralList node) {
    memorySet.registerAllocation(node);
    memorySet.killAffectedBy(node);
    // TODO(sra): Set initial keyed values.
    // TODO(sra): Set initial length.
  }

  @override
  void visitIndex(HIndex node) {
    HInstruction receiver = node.receiver.nonCheck();
    HInstruction index = node.index.nonCheck();
    final existing = memorySet.lookupKeyedValue(receiver, index);
    if (existing != null) {
      checkNewGvnCandidates(node, existing);
      final block = node.block!;
      block.rewriteWithBetterUser(node, existing);
      block.remove(node);
    } else {
      memorySet.registerKeyedValue(receiver, index, node);
    }
  }

  @override
  void visitIndexAssign(HIndexAssign node) {
    HInstruction receiver = node.receiver.nonCheck();
    memorySet.registerKeyedValueUpdate(
      receiver,
      node.index.nonCheck(),
      node.value,
    );
  }

  // Pure operations that do not escape their inputs.
  @override
  void visitBinaryArithmetic(HBinaryArithmetic node) {}
  @override
  void visitBoundsCheck(HBoundsCheck node) {}
  @override
  void visitConstant(HConstant node) {}
  @override
  void visitIf(HIf node) {}
  @override
  void visitInterceptor(HInterceptor node) {}
  @override
  void visitNot(HNot node) {}
  @override
  void visitNullCheck(HNullCheck node) {}
  @override
  void visitLateReadCheck(HLateReadCheck node) {}
  @override
  void visitParameterValue(HParameterValue node) {}
  @override
  void visitRelational(HRelational node) {}
  @override
  void visitStringConcat(HStringConcat node) {}
  @override
  void visitTypeKnown(HTypeKnown node) {}
}

/// A non-field based feature of an object.
enum MemoryFeature {
  // Access to the `length` property of a `JSIndexable`.
  length,
}

/// Holds values of memory places.
///
/// Generally, values that name a place (a receiver) have type refinements and
/// other checks removed to ensure that checks and type refinements do not
/// confuse aliasing.  Values stored into a memory place keep the type
/// refinements to help further optimizations.
class MemorySet {
  final JClosedWorld closedWorld;

  /// Maps a field to a map of receivers to their current field values.
  ///
  /// The field is either a [FieldEntity], a [FunctionEntity] in case of
  /// instance methods, or a [MemoryFeature] for `length` access on
  /// `JSIndexable`.
  ///
  /// The receiver is `null` for static and top-level fields.
  ///
  /// Sometimes `null` is stored in the map instead of deleting an entry to
  /// avoid ConcurrentModificationError.
  // TODO(25544): Split length effects from other effects and model lengths
  // separately.
  final Map<
    Object /*MemberEntity|MemoryFeature*/,
    Map<HInstruction?, HInstruction?>
  >
  fieldValues = {};

  /// Maps a receiver to a map of keys to value.
  final Map<HInstruction, Map<HInstruction, HInstruction?>> keyedValues = {};

  /// Set of objects that we know don't escape (or have not yet escaped) the
  /// current function.
  final Setlet<HInstruction> nonEscapingReceivers = Setlet();

  MemorySet(this.closedWorld);

  AbstractValueDomain get _abstractValueDomain =>
      closedWorld.abstractValueDomain;

  /// Returns whether [first] and [second] always alias to the same object.
  bool mustAlias(HInstruction? first, HInstruction? second) {
    return first == second;
  }

  /// Returns whether [first] and [second] may alias to the same object.
  bool mayAlias(HInstruction? first, HInstruction? second) {
    if (mustAlias(first, second)) return true;
    if (isConcrete(first) && isConcrete(second)) return false;
    if (nonEscapingReceivers.contains(first)) return false;
    if (nonEscapingReceivers.contains(second)) return false;
    // Typed arrays of different types might have a shared buffer.
    if (couldBeTypedArray(first!) && couldBeTypedArray(second!)) return true;
    return _abstractValueDomain
        .areDisjoint(first.instructionType, second!.instructionType)
        .isPotentiallyFalse;
  }

  bool isFinal(Object element) {
    return element is MemberEntity && closedWorld.fieldNeverChanges(element);
  }

  bool isConcrete(HInstruction? instruction) {
    return instruction is HCreate ||
        instruction is HConstant ||
        instruction is HLiteralList;
  }

  bool couldBeTypedArray(HInstruction receiver) {
    return closedWorld.abstractValueDomain
        .couldBeTypedArray(receiver.instructionType)
        .isPotentiallyTrue;
  }

  /// Returns whether [receiver] escapes the current function.
  bool escapes(HInstruction? receiver) {
    assert(receiver == null || receiver == receiver.nonCheck());
    return !nonEscapingReceivers.contains(receiver);
  }

  /// Kills locations that are imprecise due to many possible edges from
  /// instructions in the try region that can throw.
  void killLocationsForExceptionEdge() {
    // Ideally we would treat each strong (must) update in the try region as a
    // weak (may) update at the catch block, but we don't track this. The
    // conservative approximation is to kill everything.
    //
    // Aliases can be retained because they are not updated - they are generated
    // by an allocation and are killed by escaping. There is an edge from any
    // exit from the try region to the catch block which accounts for the kills
    // via escapes. Similarly, array lengths don't have updates (set:length is
    // modeled as an escape which kills the length on some path), so lengths
    // don't need to be killed here.
    //
    // TODO(sra): A more precise accounting of the effects in the try region
    // might improve precision.
    fieldValues.forEach((key, map) {
      if (key != MemoryFeature.length) {
        map.clear();
      }
    });
    keyedValues.clear();
  }

  void registerAllocation(HInstruction instruction) {
    assert(instruction == instruction.nonCheck());
    nonEscapingReceivers.add(instruction);
  }

  /// Sets the [field] on [receiver] to contain [value]. Kills all potential
  /// places that may be affected by this update. Returns `true` if the update
  /// is redundant.
  bool registerFieldValueUpdate(
    Object field,
    HInstruction? receiver,
    HInstruction value,
  ) {
    assert(
      field is MemberEntity || field is MemoryFeature,
      "Unexpected member/feature: $field",
    );
    assert(receiver == null || receiver == receiver.nonCheck());
    if (field is MemberEntity && closedWorld.nativeData.isNativeMember(field)) {
      return false; // TODO(14955): Remove this restriction?
    }
    // [value] is being set in some place in memory, we remove it from the
    // non-escaping set.
    nonEscapingReceivers.remove(value.nonCheck());
    final map = fieldValues.putIfAbsent(field, () => {});
    bool isRedundant = map[receiver] == value;
    map.forEach((key, value) {
      if (mayAlias(receiver, key)) map[key] = null;
    });
    map[receiver] = value;
    return isRedundant;
  }

  /// Registers that the [field] on [receiver] is now [value].
  void registerFieldValue(
    Object field,
    HInstruction? receiver,
    HInstruction value,
  ) {
    assert(
      field is MemberEntity || field is MemoryFeature,
      "Unexpected member/feature: $field",
    );
    assert(receiver == null || receiver == receiver.nonCheck());
    if (field is MemberEntity && closedWorld.nativeData.isNativeMember(field)) {
      return; // TODO(14955): Remove this restriction?
    }
    final map = fieldValues.putIfAbsent(field, () => {});
    map[receiver] = value;
  }

  /// Returns the value stored for [field] on [receiver]. Returns `null` if we
  /// don't know.
  HInstruction? lookupFieldValue(Object field, HInstruction? receiver) {
    assert(
      field is MemberEntity || field is MemoryFeature,
      "Unexpected member/feature: $field",
    );
    assert(receiver == null || receiver == receiver.nonCheck());
    final map = fieldValues[field];
    return (map == null) ? null : map[receiver];
  }

  /// Kill all places that may be affected by this [instruction]. Also update
  /// the set of non-escaping objects in case [instruction] has non-escaping
  /// objects in its inputs.
  void killAffectedBy(HInstruction instruction) {
    // Even if [instruction] does not have side effects, it may use non-escaping
    // objects and store them in a new object, which make these objects
    // escaping.
    for (var input in instruction.inputs) {
      nonEscapingReceivers.remove(input.nonCheck());
    }

    if (instruction.sideEffects.changesInstanceProperty() ||
        instruction.sideEffects.changesStaticProperty()) {
      // TODO(sra): Be more precise about removing only instance or static
      // properties.
      List<HInstruction?> receiversToRemove = [];

      List<Object>? fieldsToRemove;
      fieldValues.forEach((Object element, map) {
        if (isFinal(element)) return;
        map.forEach((receiver, value) {
          if (escapes(receiver)) {
            receiversToRemove.add(receiver);
          }
        });
        if (receiversToRemove.length == map.length) {
          // Remove them all by removing the entire map.
          (fieldsToRemove ??= []).add(element);
        } else {
          receiversToRemove.forEach(map.remove);
        }
        receiversToRemove.clear();
      });
      fieldsToRemove?.forEach(fieldValues.remove);
    }

    if (instruction.sideEffects.changesIndex()) {
      keyedValues.forEach((receiver, map) {
        if (escapes(receiver)) {
          map.forEach((index, value) {
            map[index] = null;
          });
        }
      });
    }
  }

  /// Returns the value stored in `receiver[index]`. Returns null if we don't
  /// know.
  HInstruction? lookupKeyedValue(HInstruction receiver, HInstruction index) {
    final map = keyedValues[receiver];
    return (map == null) ? null : map[index];
  }

  /// Registers that `receiver[index]` is now [value].
  void registerKeyedValue(
    HInstruction receiver,
    HInstruction index,
    HInstruction value,
  ) {
    final map = keyedValues.putIfAbsent(receiver, () => {});
    map[index] = value;
  }

  /// Sets `receiver[index]` to contain [value]. Kills all potential places that
  /// may be affected by this update.
  void registerKeyedValueUpdate(
    HInstruction receiver,
    HInstruction index,
    HInstruction value,
  ) {
    nonEscapingReceivers.remove(value.nonCheck());
    keyedValues.forEach((key, values) {
      if (mayAlias(receiver, key)) {
        // Typed arrays that are views of the same buffer may have different
        // offsets or element sizes, unless they are the same typed array.
        bool weakIndex = couldBeTypedArray(key) && !mustAlias(receiver, key);
        values.forEach((otherIndex, otherValue) {
          if (weakIndex || mayAlias(index, otherIndex)) {
            values[otherIndex] = null;
          }
        });
      }
    });

    // Typed arrays may narrow incoming values.
    if (couldBeTypedArray(receiver)) return;

    final map = keyedValues.putIfAbsent(receiver, () => {});
    map[index] = value;
  }

  /// Returns a common instruction for [first] and [second].
  ///
  /// Returns `null` if either [first] or [second] is null. Returns [first] if
  /// [first] and [second] are equal. Otherwise creates or re-uses a phi in
  /// [block] that holds [first] and [second].
  HInstruction? findCommonInstruction(
    HInstruction? first,
    HInstruction? second,
    HBasicBlock block,
    int predecessorIndex,
  ) {
    if (first == null || second == null) return null;
    if (first == second) return first;
    if (second is HGetLength) {
      // Don't always create phis for HGetLength. The phi confuses array bounds
      // check elimination and the resulting variable-heavy code probably is
      // confusing for JavaScript VMs. In practice, this mostly affects the
      // expansion of for-in loops on Arrays, so we match the expression
      //
      //     checkConcurrentModificationError(array.length == _end, array)
      //
      // starting with the HGetLength of the `array.length`, in the case where
      // `array.length` is not used elsewhere (i.e. not already optimized to use
      // a previous use, in the loop condition).
      //
      // TODO(sra): Figure out a better way ensure 'nice' loop code.
      // TODO(22407): The phi would not be so bad if it did not confuse bounds
      // check elimination.
      // TODO(25437): We could add a phi if we undid the harmful cases.
      if (second.usedBy.length == 1) {
        var user = second.usedBy.single;
        if (user is HIdentity && user.usedBy.length == 1) {
          HInstruction user2 = user.usedBy.single;
          if (user2 is HInvokeStatic &&
              closedWorld.commonElements.isCheckConcurrentModificationError(
                user2.element,
              )) {
            return null;
          }
        }
      }
    }
    AbstractValue phiType = _abstractValueDomain.union(
      second.instructionType,
      first.instructionType,
    );
    if (first is HPhi && first.block == block) {
      HPhi phi = first;
      phi.addInput(second);
      phi.instructionType = phiType;
      return phi;
    } else {
      HPhi phi = HPhi.noInputs(null, phiType);
      block.addPhi(phi);
      // Previous predecessors had the same input. A phi must have
      // the same number of inputs as its block has predecessors.
      for (int i = 0; i < predecessorIndex; i++) {
        phi.addInput(first);
      }
      phi.addInput(second);
      return phi;
    }
  }

  /// Returns the intersection between this [MemorySet] and the [other] memory
  /// set.
  MemorySet intersectionFor(
    MemorySet? other,
    HBasicBlock block,
    int predecessorIndex,
  ) {
    MemorySet result = MemorySet(closedWorld);
    if (other == null) {
      // This is the first visit to a loop header ([other] is `null` because we
      // have not visited the back edge). Copy the nonEscapingReceivers that are
      // guaranteed to survive the loop because they are not escaped before
      // method exit.
      // TODO(sra): We should do a proper dataflow to find the maximal
      // nonEscapingReceivers (a variant of Available-Expressions), which must
      // converge before we edit the program in [findCommonInstruction].
      for (HInstruction instruction in nonEscapingReceivers) {
        bool isNonEscapingUse(HInstruction use) {
          if (use is HReturn) return true; // Escapes, but so does control.
          if (use is HFieldGet) return true;
          if (use is HFieldSet) {
            return use.value.nonCheck() != instruction;
          }
          if (use is HGetLength) return true;
          if (use is HBoundsCheck) return true;
          if (use is HIndex) return true;
          if (use is HIndexAssign) {
            return use.value.nonCheck() != instruction;
          }
          if (use is HInterceptor) return true;
          if (use is HInvokeDynamicMethod) {
            final element = use.element;
            if (element != null) {
              if (element == closedWorld.commonElements.jsArrayAdd) {
                return use.inputs.last != instruction;
              }
            }
          }
          if (use is HInvokeStatic) {
            if (closedWorld.commonElements.isCheckConcurrentModificationError(
              use.element,
            )) {
              return true;
            }
          }

          return false;
        }

        if (instruction.usedBy.every(isNonEscapingUse)) {
          result.nonEscapingReceivers.add(instruction);
        }
      }
      return result;
    }

    fieldValues.forEach((element, values) {
      var otherValues = other.fieldValues[element];
      if (otherValues == null) return;
      values.forEach((receiver, value) {
        final instruction = findCommonInstruction(
          value,
          otherValues[receiver],
          block,
          predecessorIndex,
        );
        if (instruction != null) {
          result.registerFieldValue(element, receiver, instruction);
        }
      });
    });

    keyedValues.forEach((receiver, values) {
      var otherValues = other.keyedValues[receiver];
      if (otherValues == null) return;
      values.forEach((index, value) {
        final instruction = findCommonInstruction(
          value,
          otherValues[index],
          block,
          predecessorIndex,
        );
        if (instruction != null) {
          result.registerKeyedValue(receiver, index, instruction);
        }
      });
    });

    for (var receiver in nonEscapingReceivers) {
      if (other.nonEscapingReceivers.contains(receiver)) {
        result.nonEscapingReceivers.add(receiver);
      }
    }
    return result;
  }

  /// Returns a copy of this [MemorySet].
  MemorySet clone() {
    MemorySet result = MemorySet(closedWorld);

    fieldValues.forEach((element, values) {
      result.fieldValues[element] = Map.of(values);
    });

    keyedValues.forEach((receiver, values) {
      result.keyedValues[receiver] = Map.of(values);
    });

    result.nonEscapingReceivers.addAll(nonEscapingReceivers);
    return result;
  }

  /// Returns a copy of this [MemorySet], removing any expressions that are not
  /// valid in [block].
  MemorySet cloneIfDominatesBlock(HBasicBlock block) {
    bool instructionDominatesBlock(HInstruction? instruction) {
      return instruction != null && instruction.block!.dominates(block);
    }

    MemorySet result = MemorySet(closedWorld);

    fieldValues.forEach((element, values) {
      values.forEach((receiver, value) {
        if ((receiver == null || instructionDominatesBlock(receiver)) &&
            instructionDominatesBlock(value)) {
          result.registerFieldValue(element, receiver, value!);
        }
      });
    });

    keyedValues.forEach((receiver, values) {
      if (instructionDominatesBlock(receiver)) {
        values.forEach((index, value) {
          if (instructionDominatesBlock(index) &&
              instructionDominatesBlock(value)) {
            result.registerKeyedValue(receiver, index, value!);
          }
        });
      }
    });

    result.nonEscapingReceivers.addAll(
      nonEscapingReceivers.where(instructionDominatesBlock),
    );
    return result;
  }
}
