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

import 'package:js_runtime/synced/array_flags.dart' show ArrayFlags;
import '../common/elements.dart' show JCommonElements;
import '../constants/constant_system.dart' as constant_system;
import '../constants/values.dart';
import '../elements/entities.dart';
import '../elements/names.dart';
import '../inferrer/abstract_value_domain.dart';
import '../inferrer/types.dart';
import '../js_model/js_world.dart' show JClosedWorld;
import '../universe/selector.dart';
import 'logging.dart';
import 'nodes.dart';
import 'types.dart';

/// [InvokeDynamicSpecializer] and its subclasses are helpers to
/// optimize intercepted dynamic calls. It knows what input types
/// would be beneficial for performance, and how to change a invoke
/// dynamic to a builtin instruction (e.g. HIndex, HBitNot).
class InvokeDynamicSpecializer {
  const InvokeDynamicSpecializer();

  AbstractValue computeTypeFromInputTypes(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    return AbstractValueFactory.inferredResultTypeForSelector(
      instruction.selector,
      instruction.receiverType,
      results,
    );
  }

  HInstruction? tryConvertToBuiltin(
    HInvokeDynamic instruction,
    HGraph graph,
    GlobalTypeInferenceResults results,
    JCommonElements commonElements,
    JClosedWorld closedWorld,
    OptimizationTestLog? log,
  ) {
    return null;
  }

  void clearAllSideEffects(HInstruction instruction) {
    instruction.sideEffects.clearAllSideEffects();
    instruction.sideEffects.clearAllDependencies();
    instruction.setUseGvn();
  }

  void redirectSelector(
    HInvokeDynamic instruction,
    String name,
    JCommonElements commonElements,
  ) {
    Selector selector = instruction.selector;
    if (selector.name == name) return;
    instruction.selector = Selector.call(
      Name(name, commonElements.interceptorsLibrary!.canonicalUri),
      selector.callStructure,
    );
  }

  constant_system.Operation? operation() => null;

  static InvokeDynamicSpecializer lookupSpecializer(Selector selector) {
    if (selector.isIndex) return const IndexSpecializer();
    if (selector.isIndexSet) return const IndexAssignSpecializer();
    String name = selector.name;
    if (selector.isOperator) {
      if (name == 'unary-') return const UnaryNegateSpecializer();
      if (name == '~') return const BitNotSpecializer();
      if (name == '+') return const AddSpecializer();
      if (name == '-') return const SubtractSpecializer();
      if (name == '*') return const MultiplySpecializer();
      if (name == '/') return const DivideSpecializer();
      if (name == '~/') return const TruncatingDivideSpecializer();
      if (name == '%') return const ModuloSpecializer();
      if (name == '<<') return const ShiftLeftSpecializer();
      if (name == '>>') return const ShiftRightSpecializer();
      if (name == '>>>') return const ShiftRightUnsignedSpecializer();
      if (name == '&') return const BitAndSpecializer();
      if (name == '|') return const BitOrSpecializer();
      if (name == '^') return const BitXorSpecializer();
      if (name == '==') return const EqualsSpecializer();
      if (name == '<') return const LessSpecializer();
      if (name == '<=') return const LessEqualSpecializer();
      if (name == '>') return const GreaterSpecializer();
      if (name == '>=') return const GreaterEqualSpecializer();
      return const InvokeDynamicSpecializer();
    }
    if (selector.isCall) {
      if (selector.namedArguments.isEmpty) {
        int argumentCount = selector.argumentCount;
        if (argumentCount == 0) {
          if (name == 'abs') return const AbsSpecializer();
          if (name == 'removeLast') return const RemoveLastSpecializer();
          if (name == 'round') return const RoundSpecializer();
          if (name == 'toInt') return const ToIntSpecializer();
          if (name == 'trim') return const TrimSpecializer();
        } else if (argumentCount == 1) {
          if (name == 'codeUnitAt') return const CodeUnitAtSpecializer();
          if (name == 'compareTo') return const CompareToSpecializer();
          if (name == 'remainder') return const RemainderSpecializer();
          if (name == 'substring') return const SubstringSpecializer();
          if (name == 'contains') return const PatternMatchSpecializer();
          if (name == 'indexOf') return const PatternMatchSpecializer();
          if (name == 'startsWith') return const PatternMatchSpecializer();
          if (name == 'endsWith') return const PatternMatchSpecializer();
        } else if (argumentCount == 2) {
          if (name == 'substring') return const SubstringSpecializer();
          if (name == 'contains') return const PatternMatchSpecializer();
          if (name == 'indexOf') return const PatternMatchSpecializer();
          if (name == 'startsWith') return const PatternMatchSpecializer();
          if (name == 'endsWith') return const PatternMatchSpecializer();
        }
      }
    }
    return const InvokeDynamicSpecializer();
  }

  bool requiresBoundsCheck(HInvokeDynamic node, JClosedWorld closedWorld) {
    if (node.isBoundsSafe) return false;
    return closedWorld.annotationsData
        .getIndexBoundsCheckPolicy(node.instructionContext)
        .isEmitted;
  }

  HBoundsCheck insertBoundsCheck(
    HInvokeDynamic indexerNode,
    HInstruction array,
    HInstruction indexArgument,
    JClosedWorld closedWorld,
    OptimizationTestLog? log,
  ) {
    final abstractValueDomain = closedWorld.abstractValueDomain;
    final block = indexerNode.block!;

    if (abstractValueDomain.isNull(array.instructionType).isPotentiallyTrue) {
      HNullCheck check =
          HNullCheck(
              array,
              abstractValueDomain.excludeNull(array.instructionType),
            )
            ..selector = indexerNode.selector
            ..sourceInformation = indexerNode.sourceInformation;
      log?.registerNullCheck(indexerNode, check);
      block.addBefore(indexerNode, check);
      array = check;
    }

    HGetLength length = HGetLength(
      array,
      abstractValueDomain.positiveIntType,
      isAssignable:
          abstractValueDomain
              .isFixedLengthJsIndexable(array.instructionType)
              .isPotentiallyFalse,
    );
    block.addBefore(indexerNode, length);

    AbstractValue type =
        indexArgument.isPositiveInteger(abstractValueDomain).isDefinitelyTrue
            ? indexArgument.instructionType
            : abstractValueDomain.positiveIntType;
    HBoundsCheck check = HBoundsCheck(indexArgument, length, array, type)
      ..sourceInformation = indexerNode.sourceInformation;
    block.addBefore(indexerNode, check);
    // TODO(sra): This should be useful but causes some crashes. Figure out why:
    //     indexArgument.replaceAllUsersDominatedBy(indexerNode, check);
    return check;
  }
}

bool canBeNegativeZero(HInstruction input) {
  bool canBePositiveZero(HInstruction input) {
    if (input is HConstant) {
      ConstantValue value = input.constant;
      if (value is DoubleConstantValue && value.isZero) return true;
      if (value is IntConstantValue && value.isZero) return true;
      return false;
    }
    return true;
  }

  if (input is HConstant) {
    ConstantValue value = input.constant;
    if (value is DoubleConstantValue && value.isMinusZero) return true;
    return false;
  }
  if (input is HAdd) {
    // '+' can only generate -0.0 when both inputs are -0.0.
    return canBeNegativeZero(input.left) && canBeNegativeZero(input.right);
  }
  if (input is HSubtract) {
    // '-' can only generate -0.0 for inputs `-0.0` and `0`.
    return canBeNegativeZero(input.left) && canBePositiveZero(input.right);
  }
  if (input is HPhi) {
    final inputBlockId = input.block!.id;
    if (input.inputs.any((phiInput) => phiInput.block!.id >= inputBlockId)) {
      return true; // Assume back-edge may be negative zero.
    }
    return input.inputs.any(canBeNegativeZero);
  }
  return true;
}

class IndexAssignSpecializer extends InvokeDynamicSpecializer {
  const IndexAssignSpecializer();

  @override
  HInstruction? tryConvertToBuiltin(
    HInvokeDynamic instruction,
    HGraph graph,
    GlobalTypeInferenceResults results,
    JCommonElements commonElements,
    JClosedWorld closedWorld,
    OptimizationTestLog? log,
  ) {
    HInstruction receiver = instruction.inputs[1];
    HInstruction index = instruction.inputs[2];
    final abstractValueDomain = closedWorld.abstractValueDomain;

    bool needsMutableCheck = false;
    if (abstractValueDomain
        .isTypedArray(receiver.instructionType)
        .isDefinitelyTrue) {
      needsMutableCheck = true;
    } else if (receiver.isArray(abstractValueDomain).isDefinitelyTrue) {
      needsMutableCheck =
          receiver.isMutableArray(abstractValueDomain).isPotentiallyFalse;
    } else {
      if (receiver.isMutableIndexable(abstractValueDomain).isPotentiallyFalse) {
        return null;
      }
    }
    // TODO(johnniwinther): Merge this and the following if statement.
    if (index.isInteger(abstractValueDomain).isPotentiallyFalse &&
            // TODO(johnniwinther): Support annotations on the possible targets
            // and used their parameter check policy here.
            closedWorld
            .annotationsData
            .getParameterCheckPolicy(null)
            .isEmitted) {
      // We want the right checked mode error.
      return null;
    }

    HInstruction value = instruction.inputs[3];
    // TODO(johnniwinther): Support annotations on the possible targets
    // and used their parameter check policy here.
    if (closedWorld.annotationsData.getParameterCheckPolicy(null).isEmitted) {
      if (!_valueParameterCheckAlwaysSucceeds(
        instruction,
        receiver,
        value,
        commonElements,
        closedWorld,
      )) {
        return null;
      }
    }

    if (needsMutableCheck) {
      HInstruction getFlags = HArrayFlagsGet(
        receiver,
        abstractValueDomain.uint31Type,
      )..sourceInformation = instruction.sourceInformation;
      instruction.block!.addBefore(instruction, getFlags);
      HInstruction mask = graph.addConstantInt(
        ArrayFlags.unmodifiableCheck,
        closedWorld,
      );
      HInstruction name = graph.addConstantString('[]=', closedWorld);
      HInstruction verb = graph.addConstantString('modify', closedWorld);
      final instructionType = receiver.instructionType;
      final checkFlags = HArrayFlagsCheck(
        receiver,
        getFlags,
        mask,
        name,
        verb,
        instructionType,
      )..sourceInformation = instruction.sourceInformation;
      instruction.block!.addBefore(instruction, checkFlags);
      checkFlags.instructionType = checkFlags.computeInstructionType(
        instructionType,
        abstractValueDomain,
      );
      receiver = checkFlags;
    }

    HInstruction checkedIndex = index;
    if (requiresBoundsCheck(instruction, closedWorld)) {
      checkedIndex = insertBoundsCheck(
        instruction,
        receiver,
        index,
        closedWorld,
        log,
      );
    }
    HIndexAssign converted = HIndexAssign(receiver, checkedIndex, value);
    log?.registerIndexAssign(instruction, converted);
    return converted;
  }

  /// Returns [true] if [value] meets the requirements for being stored into
  /// indexable [receiver].
  bool _valueParameterCheckAlwaysSucceeds(
    HInvokeDynamic instruction,
    HInstruction receiver,
    HInstruction value,
    JCommonElements commonElements,
    JClosedWorld closedWorld,
  ) {
    if (instruction.isInvariant) {
      return true;
    }
    // Handle typed arrays by recognizing the exact implementation of `[]=` and
    // checking if [value] has the appropriate type.
    if (instruction.element != null) {
      ClassEntity? cls = instruction.element!.enclosingClass;
      if (cls == commonElements.typedArrayOfIntClass) {
        return value
            .isInteger(closedWorld.abstractValueDomain)
            .isDefinitelyTrue;
      } else if (cls == commonElements.typedArrayOfDoubleClass) {
        return value.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue;
      }
    }

    // The type check will pass if it passed before. We know it passed before if
    // the value was loaded from the same indexable.
    if (value is HIndex) {
      if (value.receiver.nonCheck() == receiver.nonCheck()) {
        return true;
      }
    }

    return false;
  }
}

class IndexSpecializer extends InvokeDynamicSpecializer {
  const IndexSpecializer();

  @override
  constant_system.BinaryOperation operation() {
    return constant_system.index;
  }

  @override
  HInstruction? tryConvertToBuiltin(
    HInvokeDynamic instruction,
    HGraph graph,
    GlobalTypeInferenceResults results,
    JCommonElements commonElements,
    JClosedWorld closedWorld,
    OptimizationTestLog? log,
  ) {
    HInstruction receiver = instruction.getDartReceiver(closedWorld);
    var abstractValueDomain = closedWorld.abstractValueDomain;
    if (receiver.isIndexablePrimitive(abstractValueDomain).isPotentiallyFalse) {
      return null;
    }
    HInstruction index = instruction.inputs.last;
    if (index.isInteger(abstractValueDomain).isPotentiallyFalse &&
            // TODO(johnniwinther): Support annotations on the possible targets
            // and used their parameter check policy here.
            closedWorld
            .annotationsData
            .getParameterCheckPolicy(null)
            .isEmitted) {
      // We want the right checked mode error.
      return null;
    }
    AbstractValue receiverType = receiver.instructionType;
    AbstractValue elementType =
        AbstractValueFactory.inferredResultTypeForSelector(
          instruction.selector,
          receiverType,
          results,
        );
    if (abstractValueDomain.isTypedArray(receiverType).isDefinitelyTrue) {
      elementType = abstractValueDomain.excludeNull(elementType);
    }

    HInstruction checkedIndex = index;
    if (requiresBoundsCheck(instruction, closedWorld)) {
      checkedIndex = insertBoundsCheck(
        instruction,
        receiver,
        index,
        closedWorld,
        log,
      );
    }
    HIndex converted = HIndex(receiver, checkedIndex, elementType);
    log?.registerIndex(instruction, converted);
    return converted;
  }
}

class CodeUnitAtSpecializer extends InvokeDynamicSpecializer {
  const CodeUnitAtSpecializer();

  @override
  constant_system.BinaryOperation operation() {
    return constant_system.codeUnitAt;
  }

  @override
  HInstruction? tryConvertToBuiltin(
    HInvokeDynamic instruction,
    HGraph graph,
    GlobalTypeInferenceResults results,
    JCommonElements commonElements,
    JClosedWorld closedWorld,
    OptimizationTestLog? log,
  ) {
    final abstractValueDomain = closedWorld.abstractValueDomain;
    HInstruction receiver = instruction.getDartReceiver(closedWorld);
    if (receiver.isStringOrNull(abstractValueDomain).isPotentiallyFalse) {
      return null;
    }
    HInstruction index = instruction.inputs.last;
    if (index.isInteger(abstractValueDomain).isPotentiallyFalse) {
      return null;
    }

    HInstruction checkedIndex = index;
    if (requiresBoundsCheck(instruction, closedWorld)) {
      checkedIndex = insertBoundsCheck(
        instruction,
        receiver,
        index,
        closedWorld,
        log,
      );
    }
    final converted = HCharCodeAt(
      receiver,
      checkedIndex,
      abstractValueDomain.uint31Type,
    );
    log?.registerCodeUnitAt(instruction);
    return converted;
  }
}

class RemoveLastSpecializer extends InvokeDynamicSpecializer {
  const RemoveLastSpecializer();

  @override
  HInstruction? tryConvertToBuiltin(
    HInvokeDynamic instruction,
    HGraph graph,
    GlobalTypeInferenceResults results,
    JCommonElements commonElements,
    JClosedWorld closedWorld,
    OptimizationTestLog? log,
  ) {
    HInstruction receiver = instruction.getDartReceiver(closedWorld);
    final abstractValueDomain = closedWorld.abstractValueDomain;
    if (receiver.isExtendableArray(abstractValueDomain).isPotentiallyFalse) {
      return null;
    }

    // We are essentially inlining `result = a[a.length - 1]`. `0` is the only
    // index that can fail so we check zero directly, but we want to report the
    // error index as `-1`, so we add `-1` as an extra input that to the check.
    if (requiresBoundsCheck(instruction, closedWorld)) {
      HConstant zeroIndex = graph.addConstantInt(0, closedWorld);
      HBoundsCheck check = insertBoundsCheck(
        instruction,
        receiver,
        zeroIndex,
        closedWorld,
        log,
      );
      HInstruction minusOne = graph.addConstantInt(-1, closedWorld);
      check.inputs.add(minusOne);
      minusOne.usedBy.add(check);
    }
    // `Array.pop` is encoded as a non-intercepted call to `JSArray.removeLast`.
    // TODO(sra): Add a better encoding for `Array.pop`, perhaps a HInstruction.
    HInvokeDynamic converted = HInvokeDynamicMethod(
      instruction.selector,
      instruction.receiverType,
      [receiver], // Drop interceptor.
      instruction.instructionType,
      instruction.typeArguments,
      instruction.sourceInformation,
      isIntercepted: false,
    )..element = commonElements.jsArrayRemoveLast;
    log?.registerRemoveLast(instruction, converted);
    return converted;
  }
}

class BitNotSpecializer extends InvokeDynamicSpecializer {
  const BitNotSpecializer();

  @override
  constant_system.UnaryOperation operation() {
    return constant_system.bitNot;
  }

  @override
  AbstractValue computeTypeFromInputTypes(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    // All bitwise operations on primitive types either produce an
    // integer or throw an error.
    if (instruction.inputs[1]
        .isPrimitiveOrNull(closedWorld.abstractValueDomain)
        .isDefinitelyTrue) {
      return closedWorld.abstractValueDomain.uint32Type;
    }
    return super.computeTypeFromInputTypes(instruction, results, closedWorld);
  }

  @override
  HInstruction? tryConvertToBuiltin(
    HInvokeDynamic instruction,
    HGraph graph,
    GlobalTypeInferenceResults results,
    JCommonElements commonElements,
    JClosedWorld closedWorld,
    OptimizationTestLog? log,
  ) {
    HInstruction input = instruction.inputs[1];
    if (input.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue) {
      HBitNot converted = HBitNot(
        input,
        computeTypeFromInputTypes(instruction, results, closedWorld),
      );
      log?.registerBitNot(instruction, converted);
      return converted;
    }
    return null;
  }
}

class UnaryNegateSpecializer extends InvokeDynamicSpecializer {
  const UnaryNegateSpecializer();

  @override
  constant_system.UnaryOperation operation() {
    return constant_system.negate;
  }

  @override
  AbstractValue computeTypeFromInputTypes(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    HInstruction operand = instruction.inputs[1];
    if (operand
        .isNumberOrNull(closedWorld.abstractValueDomain)
        .isDefinitelyTrue) {
      // We have integer subclasses that represent ranges, so widen any int
      // subclass to full integer.
      if (operand
          .isIntegerOrNull(closedWorld.abstractValueDomain)
          .isDefinitelyTrue) {
        return closedWorld.abstractValueDomain.intType;
      }
      return closedWorld.abstractValueDomain.numType;
    }
    return super.computeTypeFromInputTypes(instruction, results, closedWorld);
  }

  @override
  HInstruction? tryConvertToBuiltin(
    HInvokeDynamic instruction,
    HGraph graph,
    GlobalTypeInferenceResults results,
    JCommonElements commonElements,
    JClosedWorld closedWorld,
    OptimizationTestLog? log,
  ) {
    HInstruction input = instruction.inputs[1];
    if (input.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue) {
      HNegate converted = HNegate(
        input,
        computeTypeFromInputTypes(instruction, results, closedWorld),
      );
      log?.registerUnaryNegate(instruction, converted);
      return converted;
    }
    return null;
  }
}

class AbsSpecializer extends InvokeDynamicSpecializer {
  const AbsSpecializer();

  @override
  constant_system.UnaryOperation operation() {
    return constant_system.abs;
  }

  @override
  AbstractValue computeTypeFromInputTypes(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    HInstruction input = instruction.inputs[1];
    if (input
        .isNumberOrNull(closedWorld.abstractValueDomain)
        .isDefinitelyTrue) {
      return closedWorld.abstractValueDomain.excludeNull(input.instructionType);
    }
    return super.computeTypeFromInputTypes(instruction, results, closedWorld);
  }

  @override
  HInstruction? tryConvertToBuiltin(
    HInvokeDynamic instruction,
    HGraph graph,
    GlobalTypeInferenceResults results,
    JCommonElements commonElements,
    JClosedWorld closedWorld,
    OptimizationTestLog? log,
  ) {
    HInstruction input = instruction.inputs[1];
    if (input.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue) {
      HAbs converted = HAbs(
        input,
        computeTypeFromInputTypes(instruction, results, closedWorld),
      );
      log?.registerAbs(instruction, converted);
      return converted;
    }
    return null;
  }

  void registerOptimization(
    OptimizationTestLog log,
    HInvokeDynamic original,
    HInstruction converted,
  ) {}
}

abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer {
  const BinaryArithmeticSpecializer();

  @override
  AbstractValue computeTypeFromInputTypes(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    HInstruction left = instruction.inputs[1];
    HInstruction right = instruction.inputs[2];
    if (left
            .isIntegerOrNull(closedWorld.abstractValueDomain)
            .isDefinitelyTrue &&
        right
            .isIntegerOrNull(closedWorld.abstractValueDomain)
            .isDefinitelyTrue) {
      return closedWorld.abstractValueDomain.intType;
    }
    if (left.isNumberOrNull(closedWorld.abstractValueDomain).isDefinitelyTrue) {
      return closedWorld.abstractValueDomain.numType;
    }
    return super.computeTypeFromInputTypes(instruction, results, closedWorld);
  }

  bool isBuiltin(HInvokeDynamic instruction, JClosedWorld closedWorld) {
    return instruction.inputs[1]
            .isNumber(closedWorld.abstractValueDomain)
            .isDefinitelyTrue &&
        instruction.inputs[2]
            .isNumber(closedWorld.abstractValueDomain)
            .isDefinitelyTrue;
  }

  @override
  HInstruction? tryConvertToBuiltin(
    HInvokeDynamic instruction,
    HGraph graph,
    GlobalTypeInferenceResults results,
    JCommonElements commonElements,
    JClosedWorld closedWorld,
    OptimizationTestLog? log,
  ) {
    if (isBuiltin(instruction, closedWorld)) {
      HInstruction? builtin = newBuiltinVariant(
        instruction,
        results,
        closedWorld,
      );
      if (log != null) {
        registerOptimization(log, instruction, builtin);
      }
      if (builtin != null) {
        return builtin;
      }
      // Even if there is no builtin equivalent instruction, we know
      // the instruction does not have any side effect, and that it
      // can be GVN'ed.
      clearAllSideEffects(instruction);
    }
    return null;
  }

  bool inputsAreNum(HInstruction instruction, JClosedWorld closedWorld) {
    HInstruction left = instruction.inputs[1];
    HInstruction right = instruction.inputs[2];
    return left
            .isNumberOrNull(closedWorld.abstractValueDomain)
            .isDefinitelyTrue &&
        right.isNumberOrNull(closedWorld.abstractValueDomain).isDefinitelyTrue;
  }

  bool inputsArePositiveIntegers(
    HInstruction instruction,
    JClosedWorld closedWorld,
  ) {
    HInstruction left = instruction.inputs[1];
    HInstruction right = instruction.inputs[2];
    return left
            .isPositiveIntegerOrNull(closedWorld.abstractValueDomain)
            .isDefinitelyTrue &&
        right
            .isPositiveIntegerOrNull(closedWorld.abstractValueDomain)
            .isDefinitelyTrue;
  }

  bool inputsAreUInt31(HInstruction instruction, JClosedWorld closedWorld) {
    HInstruction left = instruction.inputs[1];
    HInstruction right = instruction.inputs[2];
    return left.isUInt31(closedWorld.abstractValueDomain).isDefinitelyTrue &&
        right.isUInt31(closedWorld.abstractValueDomain).isDefinitelyTrue;
  }

  HInstruction? newBuiltinVariant(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  );

  void registerOptimization(
    OptimizationTestLog log,
    HInvokeDynamic original,
    HInstruction? converted,
  );
}

class AddSpecializer extends BinaryArithmeticSpecializer {
  const AddSpecializer();

  @override
  AbstractValue computeTypeFromInputTypes(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    if (inputsAreUInt31(instruction, closedWorld)) {
      return closedWorld.abstractValueDomain.uint32Type;
    }
    if (inputsArePositiveIntegers(instruction, closedWorld)) {
      return closedWorld.abstractValueDomain.positiveIntType;
    }
    return super.computeTypeFromInputTypes(instruction, results, closedWorld);
  }

  @override
  constant_system.BinaryOperation operation() {
    return constant_system.add;
  }

  @override
  HInstruction newBuiltinVariant(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    return HAdd(
      instruction.inputs[1],
      instruction.inputs[2],
      computeTypeFromInputTypes(instruction, results, closedWorld),
    );
  }

  @override
  void registerOptimization(
    OptimizationTestLog log,
    HInvokeDynamic original,
    HInstruction? converted,
  ) {
    log.registerAdd(original, converted);
  }
}

class DivideSpecializer extends BinaryArithmeticSpecializer {
  const DivideSpecializer();

  @override
  constant_system.BinaryOperation operation() {
    return constant_system.divide;
  }

  @override
  AbstractValue computeTypeFromInputTypes(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    HInstruction left = instruction.inputs[1];
    if (left.isNumberOrNull(closedWorld.abstractValueDomain).isDefinitelyTrue) {
      return closedWorld.abstractValueDomain.numType;
    }
    return super.computeTypeFromInputTypes(instruction, results, closedWorld);
  }

  @override
  HInstruction newBuiltinVariant(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    return HDivide(
      instruction.inputs[1],
      instruction.inputs[2],
      closedWorld.abstractValueDomain.numType,
    );
  }

  @override
  void registerOptimization(
    OptimizationTestLog log,
    HInvokeDynamic original,
    HInstruction? converted,
  ) {
    log.registerDivide(original, converted);
  }
}

class ModuloSpecializer extends BinaryArithmeticSpecializer {
  const ModuloSpecializer();

  @override
  AbstractValue computeTypeFromInputTypes(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    if (inputsArePositiveIntegers(instruction, closedWorld)) {
      return closedWorld.abstractValueDomain.positiveIntType;
    }
    return super.computeTypeFromInputTypes(instruction, results, closedWorld);
  }

  @override
  constant_system.BinaryOperation operation() {
    return constant_system.modulo;
  }

  @override
  HInstruction? newBuiltinVariant(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    // Modulo cannot be mapped to the native operator (different semantics).

    // We can use HRemainder if both inputs are non-negative and the receiver
    // cannot be -0.0.  Note that -0.0 is considered to be an int, so until we
    // track -0.0 precisely, we have to syntactically filter inputs that cannot
    // generate -0.0.

    HInstruction receiver = instruction.getDartReceiver(closedWorld);
    if (inputsArePositiveIntegers(instruction, closedWorld) &&
        !canBeNegativeZero(receiver)) {
      return HRemainder(
        instruction.inputs[1],
        instruction.inputs[2],
        computeTypeFromInputTypes(instruction, results, closedWorld),
      );
    }
    // TODO(sra):
    //   a % N -->  a & (N-1), N=2^k, where a>=0, does not have -0.0 problem.

    // TODO(sra): We could avoid problems with -0.0 if we generate x % y as (x +
    // 0) % y, but we would have to fix HAdd optimizations.

    // TODO(sra): We could replace $mod with HRemainder when we don't care about
    // a -0.0 result (e.g. a % 10 == 0, a[i % 3]). This is tricky, since we
    // don't want to ruin GVN opportunities.
    return null;
  }

  @override
  void registerOptimization(
    OptimizationTestLog log,
    HInvokeDynamic original,
    HInstruction? converted,
  ) {
    log.registerModulo(original, converted);
  }
}

class RemainderSpecializer extends BinaryArithmeticSpecializer {
  const RemainderSpecializer();

  @override
  AbstractValue computeTypeFromInputTypes(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    if (inputsArePositiveIntegers(instruction, closedWorld)) {
      return closedWorld.abstractValueDomain.positiveIntType;
    }
    return super.computeTypeFromInputTypes(instruction, results, closedWorld);
  }

  @override
  constant_system.BinaryOperation operation() {
    return constant_system.remainder;
  }

  @override
  HInstruction newBuiltinVariant(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    return HRemainder(
      instruction.inputs[1],
      instruction.inputs[2],
      computeTypeFromInputTypes(instruction, results, closedWorld),
    );
  }

  @override
  void registerOptimization(
    OptimizationTestLog log,
    HInvokeDynamic original,
    HInstruction? converted,
  ) {
    log.registerRemainder(original, converted);
  }
}

class MultiplySpecializer extends BinaryArithmeticSpecializer {
  const MultiplySpecializer();

  @override
  constant_system.BinaryOperation operation() {
    return constant_system.multiply;
  }

  @override
  AbstractValue computeTypeFromInputTypes(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    if (inputsArePositiveIntegers(instruction, closedWorld)) {
      return closedWorld.abstractValueDomain.positiveIntType;
    }
    return super.computeTypeFromInputTypes(instruction, results, closedWorld);
  }

  @override
  HInstruction newBuiltinVariant(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    return HMultiply(
      instruction.inputs[1],
      instruction.inputs[2],
      computeTypeFromInputTypes(instruction, results, closedWorld),
    );
  }

  @override
  void registerOptimization(
    OptimizationTestLog log,
    HInvokeDynamic original,
    HInstruction? converted,
  ) {
    log.registerMultiply(original, converted);
  }
}

class SubtractSpecializer extends BinaryArithmeticSpecializer {
  const SubtractSpecializer();

  @override
  constant_system.BinaryOperation operation() {
    return constant_system.subtract;
  }

  @override
  HInstruction newBuiltinVariant(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    return HSubtract(
      instruction.inputs[1],
      instruction.inputs[2],
      computeTypeFromInputTypes(instruction, results, closedWorld),
    );
  }

  @override
  void registerOptimization(
    OptimizationTestLog log,
    HInvokeDynamic original,
    HInstruction? converted,
  ) {
    log.registerSubtract(original, converted);
  }
}

class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer {
  const TruncatingDivideSpecializer();

  @override
  constant_system.BinaryOperation operation() {
    return constant_system.truncatingDivide;
  }

  @override
  AbstractValue computeTypeFromInputTypes(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    if (hasUint31Result(instruction, closedWorld)) {
      return closedWorld.abstractValueDomain.uint31Type;
    }
    if (inputsArePositiveIntegers(instruction, closedWorld)) {
      return closedWorld.abstractValueDomain.positiveIntType;
    }
    if (inputsAreNum(instruction, closedWorld)) {
      return closedWorld.abstractValueDomain.intType;
    }
    return super.computeTypeFromInputTypes(instruction, results, closedWorld);
  }

  bool isNotZero(HInstruction instruction) {
    if (instruction is HConstant) {
      ConstantValue constant = instruction.constant;
      if (constant is IntConstantValue) {
        return constant.intValue != BigInt.zero;
      }
    }
    return false;
  }

  bool isTwoOrGreater(HInstruction instruction) {
    if (instruction is HConstant) {
      ConstantValue constant = instruction.constant;
      if (constant is IntConstantValue) {
        return constant.intValue >= BigInt.two;
      }
    }
    return false;
  }

  bool hasUint31Result(HInstruction instruction, JClosedWorld closedWorld) {
    HInstruction left = instruction.inputs[1];
    HInstruction right = instruction.inputs[2];
    if (right
        .isPositiveInteger(closedWorld.abstractValueDomain)
        .isDefinitelyTrue) {
      if (left.isUInt31(closedWorld.abstractValueDomain).isDefinitelyTrue &&
          isNotZero(right)) {
        return true;
      }
      if (left.isUInt32(closedWorld.abstractValueDomain).isDefinitelyTrue &&
          isTwoOrGreater(right)) {
        return true;
      }
    }
    return false;
  }

  @override
  HInstruction? tryConvertToBuiltin(
    HInvokeDynamic instruction,
    HGraph graph,
    GlobalTypeInferenceResults results,
    JCommonElements commonElements,
    JClosedWorld closedWorld,
    OptimizationTestLog? log,
  ) {
    HInstruction right = instruction.inputs[2];
    if (isBuiltin(instruction, closedWorld)) {
      if (right
              .isPositiveInteger(closedWorld.abstractValueDomain)
              .isDefinitelyTrue &&
          isNotZero(right)) {
        if (hasUint31Result(instruction, closedWorld)) {
          HInstruction converted = newBuiltinVariant(
            instruction,
            results,
            closedWorld,
          );
          if (log != null) {
            registerOptimization(log, instruction, converted);
          }
          return converted;
        }
        // We can call _tdivFast because the rhs is a 32bit integer
        // and not 0, nor -1.
        redirectSelector(instruction, '_tdivFast', commonElements);
        if (log != null) {
          registerOptimization(log, instruction, null);
        }
      }
      clearAllSideEffects(instruction);
    }
    return null;
  }

  @override
  HInstruction newBuiltinVariant(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    return HTruncatingDivide(
      instruction.inputs[1],
      instruction.inputs[2],
      computeTypeFromInputTypes(instruction, results, closedWorld),
    );
  }

  @override
  void registerOptimization(
    OptimizationTestLog log,
    HInvokeDynamic original,
    HInstruction? converted,
  ) {
    log.registerTruncatingDivide(original, converted);
  }
}

abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer {
  const BinaryBitOpSpecializer();

  @override
  AbstractValue computeTypeFromInputTypes(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    // All bitwise operations on number types either produce an unsigned 32-bit
    // integer or throw an error.
    HInstruction left = instruction.inputs[1];
    if (left.isNumberOrNull(closedWorld.abstractValueDomain).isDefinitelyTrue) {
      return closedWorld.abstractValueDomain.uint32Type;
    }
    return super.computeTypeFromInputTypes(instruction, results, closedWorld);
  }

  bool argumentLessThan32(HInstruction instruction) {
    return argumentInRange(instruction, 0, 31);
  }

  bool argumentInRange(HInstruction instruction, int low, int high) {
    if (instruction is HConstant) {
      ConstantValue constant = instruction.constant;
      if (constant is IntConstantValue) {
        int value = constant.intValue.toInt();
        assert(constant.intValue == BigInt.from(constant.intValue.toInt()));
        return value >= low && value <= high;
      }
    }
    // TODO(sra): Integrate with the bit-width analysis in codegen.dart.
    if (instruction is HBitAnd) {
      return low == 0 &&
          (argumentInRange(instruction.inputs[0], low, high) ||
              argumentInRange(instruction.inputs[1], low, high));
    }
    return false;
  }

  bool isPositive(HInstruction instruction, JClosedWorld closedWorld) {
    // TODO: We should use the value range analysis. Currently, ranges
    // are discarded just after the analysis.
    return instruction
        .isPositiveInteger(closedWorld.abstractValueDomain)
        .isDefinitelyTrue;
  }
}

class ShiftLeftSpecializer extends BinaryBitOpSpecializer {
  const ShiftLeftSpecializer();

  @override
  constant_system.BinaryOperation operation() {
    return constant_system.shiftLeft;
  }

  @override
  HInstruction? tryConvertToBuiltin(
    HInvokeDynamic instruction,
    HGraph graph,
    GlobalTypeInferenceResults results,
    JCommonElements commonElements,
    JClosedWorld closedWorld,
    OptimizationTestLog? log,
  ) {
    HInstruction left = instruction.inputs[1];
    HInstruction right = instruction.inputs[2];
    if (left.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue) {
      if (argumentLessThan32(right)) {
        HInstruction converted = newBuiltinVariant(
          instruction,
          results,
          closedWorld,
        );
        if (log != null) {
          registerOptimization(log, instruction, converted);
        }
        return converted;
      }
      // Even if there is no builtin equivalent instruction, we know
      // the instruction does not have any side effect, and that it
      // can be GVN'ed.
      clearAllSideEffects(instruction);
      if (isPositive(right, closedWorld)) {
        redirectSelector(instruction, '_shlPositive', commonElements);
      }
      if (log != null) {
        registerOptimization(log, instruction, null);
      }
    }
    return null;
  }

  @override
  HInstruction newBuiltinVariant(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    return HShiftLeft(
      instruction.inputs[1],
      instruction.inputs[2],
      computeTypeFromInputTypes(instruction, results, closedWorld),
    );
  }

  @override
  void registerOptimization(
    OptimizationTestLog log,
    HInvokeDynamic original,
    HInstruction? converted,
  ) {
    log.registerShiftLeft(original, converted);
  }
}

class ShiftRightSpecializer extends BinaryBitOpSpecializer {
  const ShiftRightSpecializer();

  @override
  AbstractValue computeTypeFromInputTypes(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    HInstruction left = instruction.inputs[1];
    if (left.isUInt32(closedWorld.abstractValueDomain).isDefinitelyTrue) {
      return left.instructionType;
    }
    return super.computeTypeFromInputTypes(instruction, results, closedWorld);
  }

  @override
  HInstruction? tryConvertToBuiltin(
    HInvokeDynamic instruction,
    HGraph graph,
    GlobalTypeInferenceResults results,
    JCommonElements commonElements,
    JClosedWorld closedWorld,
    OptimizationTestLog? log,
  ) {
    HInstruction left = instruction.inputs[1];
    HInstruction right = instruction.inputs[2];
    if (left.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue) {
      if (argumentLessThan32(right) && isPositive(left, closedWorld)) {
        HInstruction converted = newBuiltinVariant(
          instruction,
          results,
          closedWorld,
        );
        if (log != null) {
          registerOptimization(log, instruction, converted);
        }
        return converted;
      }
      // Even if there is no builtin equivalent instruction, we know
      // the instruction does not have any side effect, and that it
      // can be GVN'ed.
      clearAllSideEffects(instruction);
      if (isPositive(right, closedWorld) && isPositive(left, closedWorld)) {
        redirectSelector(instruction, '_shrBothPositive', commonElements);
        if (log != null) {
          registerOptimization(log, instruction, null);
        }
      } else if (isPositive(left, closedWorld) &&
          right.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue) {
        redirectSelector(instruction, '_shrReceiverPositive', commonElements);
        if (log != null) {
          registerOptimization(log, instruction, null);
        }
      } else if (isPositive(right, closedWorld)) {
        redirectSelector(instruction, '_shrOtherPositive', commonElements);
        if (log != null) {
          registerOptimization(log, instruction, null);
        }
      }
    }
    return null;
  }

  @override
  HInstruction newBuiltinVariant(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    return HShiftRight(
      instruction.inputs[1],
      instruction.inputs[2],
      computeTypeFromInputTypes(instruction, results, closedWorld),
    );
  }

  @override
  constant_system.BinaryOperation operation() {
    return constant_system.shiftRight;
  }

  @override
  void registerOptimization(
    OptimizationTestLog log,
    HInvokeDynamic original,
    HInstruction? converted,
  ) {
    log.registerShiftRight(original, converted);
  }
}

class ShiftRightUnsignedSpecializer extends BinaryBitOpSpecializer {
  const ShiftRightUnsignedSpecializer();

  @override
  AbstractValue computeTypeFromInputTypes(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    HInstruction left = instruction.inputs[1];
    if (left.isUInt32(closedWorld.abstractValueDomain).isDefinitelyTrue) {
      return left.instructionType;
    }
    return super.computeTypeFromInputTypes(instruction, results, closedWorld);
  }

  @override
  HInstruction? tryConvertToBuiltin(
    HInvokeDynamic instruction,
    HGraph graph,
    GlobalTypeInferenceResults results,
    JCommonElements commonElements,
    JClosedWorld closedWorld,
    OptimizationTestLog? log,
  ) {
    HInstruction left = instruction.inputs[1];
    HInstruction right = instruction.inputs[2];
    if (left.isInteger(closedWorld.abstractValueDomain).isDefinitelyTrue) {
      if (argumentLessThan32(right)) {
        HInstruction converted = newBuiltinVariant(
          instruction,
          results,
          closedWorld,
        );
        if (log != null) {
          registerOptimization(log, instruction, converted);
        }
        return converted;
      }
      // Even if there is no builtin equivalent instruction, we know
      // the instruction does not have any side effect, and that it
      // can be GVN'ed.
      clearAllSideEffects(instruction);
      if (isPositive(right, closedWorld)) {
        redirectSelector(instruction, '_shruOtherPositive', commonElements);
        if (log != null) {
          registerOptimization(log, instruction, null);
        }
      }
    }
    return null;
  }

  @override
  HInstruction newBuiltinVariant(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    return HShiftRight(
      instruction.inputs[1],
      instruction.inputs[2],
      computeTypeFromInputTypes(instruction, results, closedWorld),
    );
  }

  @override
  constant_system.BinaryOperation operation() {
    return constant_system.shiftRightUnsigned;
  }

  @override
  void registerOptimization(
    OptimizationTestLog log,
    HInvokeDynamic original,
    HInstruction? converted,
  ) {
    log.registerShiftRightUnsigned(original, converted);
  }
}

class BitOrSpecializer extends BinaryBitOpSpecializer {
  const BitOrSpecializer();

  @override
  constant_system.BinaryOperation operation() {
    return constant_system.bitOr;
  }

  @override
  AbstractValue computeTypeFromInputTypes(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    HInstruction left = instruction.inputs[1];
    HInstruction right = instruction.inputs[2];
    if (left.isUInt31(closedWorld.abstractValueDomain).isDefinitelyTrue &&
        right.isUInt31(closedWorld.abstractValueDomain).isDefinitelyTrue) {
      return closedWorld.abstractValueDomain.uint31Type;
    }
    return super.computeTypeFromInputTypes(instruction, results, closedWorld);
  }

  @override
  HInstruction newBuiltinVariant(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    return HBitOr(
      instruction.inputs[1],
      instruction.inputs[2],
      computeTypeFromInputTypes(instruction, results, closedWorld),
    );
  }

  @override
  void registerOptimization(
    OptimizationTestLog log,
    HInvokeDynamic original,
    HInstruction? converted,
  ) {
    log.registerBitOr(original, converted);
  }
}

class BitAndSpecializer extends BinaryBitOpSpecializer {
  const BitAndSpecializer();

  @override
  constant_system.BinaryOperation operation() {
    return constant_system.bitAnd;
  }

  @override
  AbstractValue computeTypeFromInputTypes(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    HInstruction left = instruction.inputs[1];
    HInstruction right = instruction.inputs[2];
    if (left
            .isPrimitiveOrNull(closedWorld.abstractValueDomain)
            .isDefinitelyTrue &&
        (left.isUInt31(closedWorld.abstractValueDomain).isDefinitelyTrue ||
            right.isUInt31(closedWorld.abstractValueDomain).isDefinitelyTrue)) {
      return closedWorld.abstractValueDomain.uint31Type;
    }
    return super.computeTypeFromInputTypes(instruction, results, closedWorld);
  }

  @override
  HInstruction newBuiltinVariant(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    return HBitAnd(
      instruction.inputs[1],
      instruction.inputs[2],
      computeTypeFromInputTypes(instruction, results, closedWorld),
    );
  }

  @override
  void registerOptimization(
    OptimizationTestLog log,
    HInvokeDynamic original,
    HInstruction? converted,
  ) {
    log.registerBitAnd(original, converted);
  }
}

class BitXorSpecializer extends BinaryBitOpSpecializer {
  const BitXorSpecializer();

  @override
  constant_system.BinaryOperation operation() {
    return constant_system.bitXor;
  }

  @override
  AbstractValue computeTypeFromInputTypes(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    HInstruction left = instruction.inputs[1];
    HInstruction right = instruction.inputs[2];
    if (left.isUInt31(closedWorld.abstractValueDomain).isDefinitelyTrue &&
        right.isUInt31(closedWorld.abstractValueDomain).isDefinitelyTrue) {
      return closedWorld.abstractValueDomain.uint31Type;
    }
    return super.computeTypeFromInputTypes(instruction, results, closedWorld);
  }

  @override
  HInstruction newBuiltinVariant(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    return HBitXor(
      instruction.inputs[1],
      instruction.inputs[2],
      computeTypeFromInputTypes(instruction, results, closedWorld),
    );
  }

  @override
  void registerOptimization(
    OptimizationTestLog log,
    HInvokeDynamic original,
    HInstruction? converted,
  ) {
    log.registerBitXor(original, converted);
  }
}

abstract class RelationalSpecializer extends InvokeDynamicSpecializer {
  const RelationalSpecializer();

  @override
  AbstractValue computeTypeFromInputTypes(
    HInvokeDynamic instruction,
    GlobalTypeInferenceResults results,
    JClosedWorld closedWorld,
  ) {
    if (instruction.inputs[1]
        .isPrimitiveOrNull(closedWorld.abstractValueDomain)
        .isDefinitelyTrue) {
      return closedWorld.abstractValueDomain.boolType;
    }
    return super.computeTypeFromInputTypes(instruction, results, closedWorld);
  }

  @override
  HInstruction? tryConvertToBuiltin(
    HInvokeDynamic instruction,
    HGraph graph,
    GlobalTypeInferenceResults results,
    JCommonElements commonElements,
    JClosedWorld closedWorld,
    OptimizationTestLog? log,
  ) {
    HInstruction left = instruction.inputs[1];
    HInstruction right = instruction.inputs[2];
    if (left.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue &&
        right.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue) {
      HInstruction converted = newBuiltinVariant(instruction, closedWorld);
      if (log != null) {
        registerOptimization(log, instruction, converted);
      }
      return converted;
    }
    return null;
  }

  HInstruction newBuiltinVariant(
    HInvokeDynamic instruction,
    JClosedWorld closedWorld,
  );

  void registerOptimization(
    OptimizationTestLog log,
    HInvokeDynamic original,
    HInstruction converted,
  );
}

class EqualsSpecializer extends RelationalSpecializer {
  const EqualsSpecializer();

  @override
  HInstruction? tryConvertToBuiltin(
    HInvokeDynamic instruction,
    HGraph graph,
    GlobalTypeInferenceResults results,
    JCommonElements commonElements,
    JClosedWorld closedWorld,
    OptimizationTestLog? log,
  ) {
    HInstruction left = instruction.inputs[1];
    HInstruction right = instruction.inputs[2];
    AbstractValue instructionType = left.instructionType;
    if (right.isConstantNull() ||
        left
            .isPrimitiveOrNull(closedWorld.abstractValueDomain)
            .isDefinitelyTrue) {
      HInstruction converted = newBuiltinVariant(instruction, closedWorld);
      if (log != null) {
        registerOptimization(log, instruction, converted);
      }
      return converted;
    }
    if (closedWorld.includesClosureCall(
      instruction.selector,
      instructionType,
    )) {
      return null;
    }
    Iterable<MemberEntity> matches = closedWorld.locateMembers(
      instruction.selector,
      instructionType,
    );
    // This test relies on `Object.==` and `Interceptor.==` always being
    // implemented because if the selector matches by subtype, it still will be
    // a regular object or an interceptor.
    if (matches.every(
      closedWorld.commonElements.isDefaultEqualityImplementation,
    )) {
      HInstruction converted = newBuiltinVariant(instruction, closedWorld);
      if (log != null) {
        registerOptimization(log, instruction, converted);
      }
      return converted;
    }
    return null;
  }

  @override
  constant_system.BinaryOperation operation() {
    return constant_system.equal;
  }

  @override
  HInstruction newBuiltinVariant(
    HInvokeDynamic instruction,
    JClosedWorld closedWorld,
  ) {
    return HIdentity(
      instruction.inputs[1],
      instruction.inputs[2],
      closedWorld.abstractValueDomain.boolType,
    );
  }

  @override
  void registerOptimization(
    OptimizationTestLog log,
    HInvokeDynamic original,
    HInstruction converted,
  ) {
    log.registerEquals(original, converted);
  }
}

class LessSpecializer extends RelationalSpecializer {
  const LessSpecializer();

  @override
  constant_system.BinaryOperation operation() {
    return constant_system.less;
  }

  @override
  HInstruction newBuiltinVariant(
    HInvokeDynamic instruction,
    JClosedWorld closedWorld,
  ) {
    return HLess(
      instruction.inputs[1],
      instruction.inputs[2],
      closedWorld.abstractValueDomain.boolType,
    );
  }

  @override
  void registerOptimization(
    OptimizationTestLog log,
    HInvokeDynamic original,
    HInstruction converted,
  ) {
    log.registerLess(original, converted);
  }
}

class GreaterSpecializer extends RelationalSpecializer {
  const GreaterSpecializer();

  @override
  constant_system.BinaryOperation operation() {
    return constant_system.greater;
  }

  @override
  HInstruction newBuiltinVariant(
    HInvokeDynamic instruction,
    JClosedWorld closedWorld,
  ) {
    return HGreater(
      instruction.inputs[1],
      instruction.inputs[2],
      closedWorld.abstractValueDomain.boolType,
    );
  }

  @override
  void registerOptimization(
    OptimizationTestLog log,
    HInvokeDynamic original,
    HInstruction converted,
  ) {
    log.registerGreater(original, converted);
  }
}

class GreaterEqualSpecializer extends RelationalSpecializer {
  const GreaterEqualSpecializer();

  @override
  constant_system.BinaryOperation operation() {
    return constant_system.greaterEqual;
  }

  @override
  HInstruction newBuiltinVariant(
    HInvokeDynamic instruction,
    JClosedWorld closedWorld,
  ) {
    return HGreaterEqual(
      instruction.inputs[1],
      instruction.inputs[2],
      closedWorld.abstractValueDomain.boolType,
    );
  }

  @override
  void registerOptimization(
    OptimizationTestLog log,
    HInvokeDynamic original,
    HInstruction converted,
  ) {
    log.registerGreaterEqual(original, converted);
  }
}

class LessEqualSpecializer extends RelationalSpecializer {
  const LessEqualSpecializer();

  @override
  constant_system.BinaryOperation operation() {
    return constant_system.lessEqual;
  }

  @override
  HInstruction newBuiltinVariant(
    HInvokeDynamic instruction,
    JClosedWorld closedWorld,
  ) {
    return HLessEqual(
      instruction.inputs[1],
      instruction.inputs[2],
      closedWorld.abstractValueDomain.boolType,
    );
  }

  @override
  void registerOptimization(
    OptimizationTestLog log,
    HInvokeDynamic original,
    HInstruction converted,
  ) {
    log.registerLessEqual(original, converted);
  }
}

class CompareToSpecializer extends InvokeDynamicSpecializer {
  const CompareToSpecializer();

  @override
  HInstruction? tryConvertToBuiltin(
    HInvokeDynamic instruction,
    HGraph graph,
    GlobalTypeInferenceResults results,
    JCommonElements commonElements,
    JClosedWorld closedWorld,
    OptimizationTestLog? log,
  ) {
    HInstruction receiver = instruction.getDartReceiver(closedWorld);
    // `compareTo` has no side-effect (other than throwing) and can be GVN'ed
    // for some known types.
    if (receiver
            .isStringOrNull(closedWorld.abstractValueDomain)
            .isDefinitelyTrue ||
        receiver
            .isNumberOrNull(closedWorld.abstractValueDomain)
            .isDefinitelyTrue) {
      // Replace `a.compareTo(a)` with `0`, but only if receiver and argument
      // are such that no exceptions can be thrown.
      HInstruction argument = instruction.inputs.last;
      if ((receiver
                  .isNumber(closedWorld.abstractValueDomain)
                  .isDefinitelyTrue &&
              argument
                  .isNumber(closedWorld.abstractValueDomain)
                  .isDefinitelyTrue) ||
          (receiver
                  .isString(closedWorld.abstractValueDomain)
                  .isDefinitelyTrue &&
              argument
                  .isString(closedWorld.abstractValueDomain)
                  .isDefinitelyTrue)) {
        if (identical(receiver.nonCheck(), argument.nonCheck())) {
          final converted = graph.addConstantInt(0, closedWorld);
          log?.registerCompareTo(instruction, converted);
          return converted;
        }
      }
      clearAllSideEffects(instruction);
      log?.registerCompareTo(instruction);
    }
    return null;
  }
}

abstract class IdempotentStringOperationSpecializer
    extends InvokeDynamicSpecializer {
  const IdempotentStringOperationSpecializer();

  @override
  HInstruction? tryConvertToBuiltin(
    HInvokeDynamic instruction,
    HGraph graph,
    GlobalTypeInferenceResults results,
    JCommonElements commonElements,
    JClosedWorld closedWorld,
    OptimizationTestLog? log,
  ) {
    HInstruction receiver = instruction.getDartReceiver(closedWorld);
    if (receiver
        .isStringOrNull(closedWorld.abstractValueDomain)
        .isDefinitelyTrue) {
      // String.xxx does not have any side effect (other than throwing), and it
      // can be GVN'ed.
      clearAllSideEffects(instruction);
      if (log != null) {
        registerOptimization(log, instruction);
      }
    }
    return null;
  }

  void registerOptimization(OptimizationTestLog log, HInvokeDynamic original);
}

class SubstringSpecializer extends IdempotentStringOperationSpecializer {
  const SubstringSpecializer();

  @override
  void registerOptimization(OptimizationTestLog log, HInvokeDynamic original) {
    log.registerSubstring(original);
  }
}

class TrimSpecializer extends IdempotentStringOperationSpecializer {
  const TrimSpecializer();

  @override
  void registerOptimization(OptimizationTestLog log, HInvokeDynamic original) {
    log.registerTrim(original);
  }
}

class PatternMatchSpecializer extends InvokeDynamicSpecializer {
  const PatternMatchSpecializer();

  @override
  HInstruction? tryConvertToBuiltin(
    HInvokeDynamic instruction,
    HGraph graph,
    GlobalTypeInferenceResults results,
    JCommonElements commonElements,
    JClosedWorld closedWorld,
    OptimizationTestLog? log,
  ) {
    HInstruction receiver = instruction.getDartReceiver(closedWorld);
    HInstruction pattern = instruction.inputs[2];
    if (receiver
            .isStringOrNull(closedWorld.abstractValueDomain)
            .isDefinitelyTrue &&
        pattern
            .isStringOrNull(closedWorld.abstractValueDomain)
            .isDefinitelyTrue) {
      // String.contains(String s) does not have any side effect (other than
      // throwing), and it can be GVN'ed.
      clearAllSideEffects(instruction);
      log?.registerPatternMatch(instruction);
    }
    return null;
  }
}

class RoundSpecializer extends InvokeDynamicSpecializer {
  const RoundSpecializer();

  @override
  constant_system.UnaryOperation operation() => constant_system.round;

  @override
  HInstruction? tryConvertToBuiltin(
    HInvokeDynamic instruction,
    HGraph graph,
    GlobalTypeInferenceResults results,
    JCommonElements commonElements,
    JClosedWorld closedWorld,
    OptimizationTestLog? log,
  ) {
    HInstruction receiver = instruction.getDartReceiver(closedWorld);
    if (receiver
        .isNumberOrNull(closedWorld.abstractValueDomain)
        .isDefinitelyTrue) {
      // Even if there is no builtin equivalent instruction, we know the
      // instruction does not have any side effect, and that it can be GVN'ed.
      clearAllSideEffects(instruction);
      log?.registerRound(instruction);
    }
    return null;
  }
}

class ToIntSpecializer extends InvokeDynamicSpecializer {
  const ToIntSpecializer();

  @override
  constant_system.UnaryOperation operation() => constant_system.toInt;

  @override
  HInstruction? tryConvertToBuiltin(
    HInvokeDynamic instruction,
    HGraph graph,
    GlobalTypeInferenceResults results,
    JCommonElements commonElements,
    JClosedWorld closedWorld,
    OptimizationTestLog? log,
  ) {
    HInstruction receiver = instruction.getDartReceiver(closedWorld);

    // We would like to reduce `x.toInt()` to `x`. The web platform considers
    // infinities to be `int` values, but it is too hard to tell if an input is
    // a finite integral value. Further `(-0.0).toInt()` returns `0`, so
    // `toInt()` is not strictly an identity on finite integral values.

    if (receiver
        .isNumberOrNull(closedWorld.abstractValueDomain)
        .isDefinitelyTrue) {
      // Even if there is no builtin equivalent instruction, we know the
      // instruction does not have any side effect, and that it can be GVN'ed.
      clearAllSideEffects(instruction);
      log?.registerToInt(instruction);
    }
    return null;
  }
}
