// 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
          .isModifiableArray(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();
    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();
    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();
    final abstractValueDomain = closedWorld.abstractValueDomain;
    if (receiver.isGrowableArray(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();
    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();
    // `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();
    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();
    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();
    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();

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