// 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.

// @dart = 2.10

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 '../universe/selector.dart';
import '../world.dart' show JClosedWorld;
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.length == 0) {
        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;

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

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

    AbstractValue type =
        indexArgument.isPositiveInteger(abstractValueDomain).isDefinitelyTrue
            ? indexArgument.instructionType
            : abstractValueDomain.positiveIntType;
    HBoundsCheck check = HBoundsCheck(indexArgument, length, array, type)
      ..sourceInformation = indexerNode.sourceInformation;
    indexerNode.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) {
    if (input.inputs.any((phiInput) => phiInput.block.id >= input.block.id)) {
      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];
    if (receiver
        .isMutableIndexable(closedWorld.abstractValueDomain)
        .isPotentiallyFalse) {
      return null;
    }
    // TODO(johnniwinther): Merge this and the following if statement.
    if (index.isInteger(closedWorld.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;
      }
    }

    HInstruction checkedIndex = index;
    if (requiresBoundsCheck(instruction, closedWorld)) {
      checkedIndex =
          insertBoundsCheck(instruction, receiver, index, closedWorld, log);
    }
    HIndexAssign converted = HIndexAssign(
        closedWorld.abstractValueDomain, 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 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, HInstruction 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, HInstruction 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, HInstruction 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(HInstruction 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, HInstruction 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 syntatically 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, HInstruction 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, HInstruction 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, HInstruction 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, HInstruction 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.isConstantInteger()) return false;
    HConstant rightConstant = instruction;
    IntConstantValue intConstant = rightConstant.constant;
    BigInt count = intConstant.intValue;
    return count != BigInt.zero;
  }

  bool isTwoOrGreater(HInstruction instruction) {
    if (!instruction.isConstantInteger()) return false;
    HConstant rightConstant = instruction;
    IntConstantValue intConstant = rightConstant.constant;
    BigInt count = intConstant.intValue;
    return count >= BigInt.two;
  }

  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, HInstruction 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.isConstantInteger()) {
      HConstant rightConstant = instruction;
      IntConstantValue intConstant = rightConstant.constant;
      int value = intConstant.intValue.toInt();
      assert(intConstant.intValue == BigInt.from(intConstant.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, HInstruction 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, HInstruction 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, HInstruction 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, HInstruction 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, HInstruction 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, HInstruction 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, HInstruction 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, HInstruction 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, HInstruction 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, HInstruction 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, HInstruction 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, HInstruction original, HInstruction converted) {
    log.registerLessEqual(original, 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) {
    // TODO(sra): Implement a builtin HCodeUnitAt instruction and the same index
    // bounds checking optimizations as for HIndex.
    HInstruction receiver = instruction.getDartReceiver(closedWorld);
    if (receiver
        .isStringOrNull(closedWorld.abstractValueDomain)
        .isDefinitelyTrue) {
      // Even if there is no builtin equivalent instruction, we know
      // String.codeUnitAt does not have any side effect (other than throwing),
      // and that it can be GVN'ed.
      clearAllSideEffects(instruction);
      if (instruction.inputs.last
          .isPositiveInteger(closedWorld.abstractValueDomain)
          .isDefinitelyTrue) {
        redirectSelector(instruction, '_codeUnitAt', commonElements);
      }
      log?.registerCodeUnitAt(instruction);
    }
    return null;
  }
}

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())) {
          HInstruction 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, HInstruction original);
}

class SubstringSpecializer extends IdempotentStringOperationSpecializer {
  const SubstringSpecializer();

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

class TrimSpecializer extends IdempotentStringOperationSpecializer {
  const TrimSpecializer();

  @override
  void registerOptimization(OptimizationTestLog log, HInstruction 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;
  }
}
