// 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 'dart:collection' show Queue;

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();
    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;
      }

      node.sideEffects.restrictTo(
        _globalInferenceResults.inferredData.getSideEffectsOfElement(element),
      );
      if (_closedWorld.annotationsData.allowCSE(element)) {
        node.allowCSE = true;
      }
      if (_closedWorld.annotationsData.allowDCE(element)) {
        node.allowDCE = true;
      }

      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) {
        // 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);
            }
          }
        }
      }
    }

    // HFieldGet of a final field from an allocator can be replaced with the
    // field's value.
    //
    // Load Elimination is more powerful as it can handle non-final fields, but
    // doing this earlier in the simplifier generates more opportunities for the
    // first GVN pass.
    if (receiver is HCreate && !node.isAssignable) {
      int index = _indexOfFieldInAllocatorInputs(
        receiver.element,
        node.element,
      );
      if (index >= 0) return receiver.inputs[index];
    }

    return node;
  }

  int _indexOfFieldInAllocatorInputs(ClassEntity cls, FieldEntity field) {
    final classCache = _indexOfFieldInAllocatorCache ??= {};
    final fieldCache = classCache[cls] ??= {};
    final index = fieldCache[field];
    if (index != null) return index;

    int argumentIndex = 0;
    _closedWorld.elementEnvironment.forEachInstanceField(cls, (
      _,
      FieldEntity member,
    ) {
      FieldAnalysisData fieldData = _closedWorld.fieldAnalysis.getFieldData(
        member,
      );
      int index = (fieldData.isElided || fieldData.isInitializedInAllocator)
          ? -1
          : argumentIndex++;

      // TODO(https://github.com/dart-lang/sdk/issues/26775): dart2js has a bug
      // with using the same mixin twice, the fields are not separated, so can
      // occur here twice. If we already have an index, one of them is wrong.
      if (fieldCache[member] != null) index = -1;

      fieldCache[member] = index;
    });

    if (fieldCache[field] == null) {
      // The field should not be missing but it might be possible (1) with
      // unsound optimizations due to 'trusted' checks (-O3), and (2) attempting
      // to compile an abstract class generative constructor (a bit unclear why
      // this happens, see b/422944368).
      return fieldCache[field] = -1;
    }
    return fieldCache[field]!;
  }

  Map<ClassEntity, Map<FieldEntity, int>>? _indexOfFieldInAllocatorCache;

  @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();
    AbstractValue receiverType = receiver.instructionType;

    Selector selector = node.selector;
    final member =
        node.element ?? _closedWorld.locateSingleMember(selector, receiverType);
    if (member == null) {
      // TODO(sra): Consider properties of the target set. If all potential
      // targets, say, allow CSE, or return fresh allocations, then so does this
      // getter call.
      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) {
      // Consider only getters - 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;
        }
        node.sideEffects.restrictTo(
          _globalInferenceResults.inferredData.getSideEffectsOfElement(member),
        );
        if (_closedWorld.annotationsData.allowCSE(member)) {
          node.allowCSE = true;
        }
        if (_closedWorld.annotationsData.allowDCE(member)) {
          node.allowDCE = true;
        }
      }
    }

    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();
    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();

    // 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.isRedundantOn(node.checkedInput, _closedWorld)) {
      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.isRedundantOn(node.checkedInput, _closedWorld)) {
      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.evaluateOn(node.checkedInput, _closedWorld);
    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.evaluateOn(node.checkedInput, _closedWorld);
    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();
    HInstruction? current = instruction.next;
    do {
      if ((current!.getDartReceiver() == 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() == instruction) return true;
      } else if (use is HFieldGet) {
        assert(use.getDartReceiver() == 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());
  }

  bool isDeadCode(HInstruction instruction) {
    if (instruction.usedBy.isNotEmpty) return false;
    if (isTrivialDeadStore(instruction)) return true;
    if (instruction.allowDCE) 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);
        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);
      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();
      if (instruction.allowCSE) {
        final other = values.lookup(instruction);
        if (other != null) {
          assert(other.gvnEquals(instruction) && instruction.gvnEquals(other));
          block.rewriteWithBetterUser(instruction, other);
          block.remove(instruction);
        } else {
          // We didn't replace the instruction with a previous value,
          values.kill(flags);
          values.add(instruction);
        }
      } else {
        assert(flags.isEmpty || !instruction.useGvn());
        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 [value] that are dominated by the start of the [dominator]
  /// block to use [TypeKnown] of [value] instead. As the type refinement
  /// depends on the control flow, we mark the inserted [HTypeKnown] nodes as
  /// non-movable.
  void insertTypeRefinement(
    HBasicBlock dominator,
    HInstruction value,
    AbstractValue convertedType,
  ) {
    DominatedUses dominatedUses = DominatedUses.of(value, 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 == value) {
        return;
      }
    }

    final replacement = HTypeKnown.pinned(convertedType, value);
    dominator.addBefore(dominator.first, replacement);
    dominatedUses.replaceWith(replacement);
  }

  void insertTypeRefinements(
    List<HBasicBlock> targets,
    HInstruction value,
    AbstractValue convertedType,
  ) {
    for (final block in targets) {
      insertTypeRefinement(block, value, convertedType);
    }
  }

  @override
  void visitIsTest(HIsTest node) {
    HInstruction input = node.checkedInput;
    if (input.usedBy.length <= 1) return; // No other uses to refine.

    final targets = ConditionTargets(node);
    if (targets.isEmpty) return;

    AbstractValue whenTrueType = node.checkedAbstractValue.abstractValue;
    insertTypeRefinements(targets.whenTrue, input, whenTrueType);
    // 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) {
    HInstruction input = node.checkedInput;
    if (input.usedBy.length <= 1) return; // No other uses to refine.

    final targets = ConditionTargets(node);
    if (targets.isEmpty) return;

    AbstractValue whenTrueType = node.checkedAbstractValue.abstractValue;
    insertTypeRefinements(targets.whenTrue, input, whenTrueType);
    // 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 (input.usedBy.length <= 1) return; // No other uses to refine.

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

    final targets = ConditionTargets(node);
    if (targets.isEmpty) return;

    AbstractValue nonNullType = _abstractValueDomain.excludeNull(
      input.instructionType,
    );
    insertTypeRefinements(targets.whenFalse, 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'.
  }

  @override
  void visitIsLateSentinel(HIsLateSentinel node) {
    final input = node.inputs.single;
    if (input.usedBy.length <= 1) return; // No other uses to refine.

    final targets = ConditionTargets(node);
    if (targets.isEmpty) return;

    final sentinelType = _abstractValueDomain.lateSentinelType;
    final nonSentinelType = _abstractValueDomain.excludeLateSentinel(
      input.instructionType,
    );
    insertTypeRefinements(targets.whenTrue, input, sentinelType);
    insertTypeRefinements(targets.whenFalse, input, nonSentinelType);
  }
}

typedef _Step = (HInstruction, {_Targets? whenTrue, _Targets? whenFalse});

/// [ConditionTargets] collects the target blocks for a condition. The target
/// blocks are blocks reachable only when the condition is true (`whenTrue`) and
/// blocks reachable only when the condition is false (`whenFalse`).
///
/// The algorithm starts with an initial condition instruction and two empty
/// sets of targets, [_trueTargets] and [_falseTargets]. If the condition is
/// used in HIf control flow, we know the condition is true in the then-block
/// and false in the else-block.
///
/// If the condition is used by HNot, we can infer that when the HNot is true,
/// the condition was false and the trueTargets of the HNot are the falseTargets
/// of the original condition. The HNot is added to a work queue with flipped
/// targets.
///
/// If the condition is used in a phi, or a HIf controlling a phi, depending on
/// how the condition is used, sometimes when the phi is true or false, we can
/// infer something about the original condition's targets.
///
/// `whenTrue:` and `whenFalse` each have three possible values, (1)
/// _trueTargets, (2) _falseTargets, and (3) `null`.
class ConditionTargets {
  /// For the visited set, only one of `whenTrue:` and `whenFalse:` used, the
  /// other is `null`. It is unusual, but possible to visit both of:
  ///
  ///     (cond, whenTrue: _trueTargets, whenFalse: null)
  ///     (cond, whenTrue: _falseTargets, whenFalse: null)
  ///
  /// This is a contradition (cond both must be true and also must be
  /// false). Contradictions happen only in unreachable code.
  final Set<_Step> _visited = {};

  final Queue<_Step> _queue = Queue();

  final _Targets _trueTargets = _Targets();
  final _Targets _falseTargets = _Targets();

  ConditionTargets(HInstruction condition) {
    _add(condition, _trueTargets, _falseTargets);
    while (_queue.isNotEmpty) {
      _step();
    }
  }

  bool get isEmpty => _trueTargets.isEmpty && _falseTargets.isEmpty;

  List<HBasicBlock> get whenTrue => _trueTargets.blocks;
  List<HBasicBlock> get whenFalse => _falseTargets.blocks;

  void _add(HInstruction node, _Targets? trueTargets, _Targets? falseTargets) {
    if (trueTargets == null && falseTargets == null) return;
    _queue.add((node, whenTrue: trueTargets, whenFalse: falseTargets));
  }

  void _step() {
    var (instruction, whenTrue: trueTargets, whenFalse: falseTargets) = _queue
        .removeFirst();

    // The same instruction (I) can be reached on different paths with different
    // combinations of trueTargets (T) and falseTargets (F).  Filling in the
    // targets for problem (I,T,F) is separable into processing (I,T,null) and
    // (I,null,F), so we check if we have visited this instruction before by
    // querying trueTargets and falseTargets independently, and remove the
    // separable subproblem that already has been solved.
    if (trueTargets != null &&
        !_visited.add((instruction, whenTrue: trueTargets, whenFalse: null))) {
      trueTargets = null;
    }
    if (falseTargets != null &&
        !_visited.add((instruction, whenTrue: null, whenFalse: falseTargets))) {
      falseTargets = null;
    }

    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.
                  _add(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.
                  _add(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.
                  _add(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.
                  _add(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 do 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) {
        _add(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].
            _add(user, null, falseTargets);
          } else if (other.isConstantFalse()) {
            // Ditto for false.
            _add(user, trueTargets, null);
          }
        }
      }
    }
  }
}

class _Targets {
  final List<HBasicBlock> _blocks = [];
  bool get isEmpty => _blocks.isEmpty;
  void add(HBasicBlock block) => _blocks.add(block);
  List<HBasicBlock> get blocks => _blocks;
}

/// 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) {
      final nonCheck = insn.nonCheck();
      return nonCheck.useGvn() || nonCheck.allowCSE;
    }

    if (instruction.usedBy.any(hasUseGvn) && existing.usedBy.any(hasUseGvn)) {
      newGvnCandidates = true;
    }
  }

  @override
  void visitFieldGet(HFieldGet node) {
    FieldEntity element = node.element;
    HInstruction receiver = node.getDartReceiver().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().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;
  }
}
