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

import 'dart:collection' show UnmodifiableMapView;

import '../constants/constant_system.dart' as constant_system;
import '../constants/values.dart';
import '../js_model/js_world.dart' show JClosedWorld;
import '../tracer.dart';
import 'nodes.dart';
import 'optimize.dart' show OptimizationPhase, SsaOptimizerWorkItem;

bool _debug = false;

class ValueRangeInfo {
  late final IntValue intZero;
  late final IntValue intOne;

  late final Value maxIntValue;
  late final Value minIntValue;
  late final Value unknownValue;

  ValueRangeInfo() {
    intZero = newIntValue(BigInt.zero);
    intOne = newIntValue(BigInt.one);

    maxIntValue = MaxIntValue(this);
    minIntValue = MinIntValue(this);
    unknownValue = UnknownValue(this);
  }

  IntValue newIntValue(BigInt value) {
    return IntValue(value, this);
  }

  InstructionValue newInstructionValue(HInstruction instruction) {
    return InstructionValue(instruction, this);
  }

  PositiveValue newPositiveValue(HInstruction instruction) {
    return PositiveValue(instruction, this);
  }

  Value newAddValue(Value left, Value right) {
    return AddValue(left, right, this);
  }

  Value newSubtractValue(Value left, Value right) {
    return SubtractValue(left, right, this);
  }

  Value newNegateValue(Value value) {
    return NegateValue(value, this);
  }

  Range newUnboundRange() {
    return Range.unbound(this);
  }

  Range newNormalizedRange(Value low, Value up) {
    return Range.normalize(low, up, this);
  }

  Value newMarkerValue({required bool isLower, required bool isPositive}) {
    return MarkerValue(isLower, isPositive, this);
  }
}

/// A [Value] represents both symbolic values like the value of a
/// parameter, or the length of an array, and concrete values, like
/// constants.
abstract class Value {
  final ValueRangeInfo info;
  const Value(this.info);

  Value operator +(Value other) => info.unknownValue;
  Value operator -(Value other) => info.unknownValue;
  Value operator -() => info.unknownValue;
  Value operator &(Value other) => info.unknownValue;

  Value min(Value other) {
    if (this == other) return this;
    if (other == info.minIntValue) return other;
    if (other == info.maxIntValue) return this;
    Value value = this - other;
    if (value.isPositive) return other;
    if (value.isNegative) return this;
    return info.unknownValue;
  }

  Value max(Value other) {
    if (this == other) return this;
    if (other == info.minIntValue) return this;
    if (other == info.maxIntValue) return other;
    Value value = this - other;
    if (value.isPositive) return this;
    if (value.isNegative) return other;
    return info.unknownValue;
  }

  Value replaceMarkers(Value lowerBound, Value upperBound) {
    return this;
  }

  bool get isNegative => false;
  bool get isPositive => false;
  bool get isZero => false;
}

/// An [IntValue] contains a constant integer value.
class IntValue extends Value {
  final BigInt value;

  const IntValue(this.value, super.info);

  @override
  Value operator +(Value other) {
    if (other.isZero) return this;
    if (other is IntValue) {
      final constant = constant_system.add.fold(
        constant_system.createInt(value),
        constant_system.createInt(other.value),
      );
      if (constant is IntConstantValue) {
        return info.newIntValue(constant.intValue);
      }
      return info.unknownValue;
    }
    return other + this;
  }

  @override
  Value operator -(Value other) {
    if (other.isZero) return this;
    if (other is IntValue) {
      final constant = constant_system.subtract.fold(
        constant_system.createInt(value),
        constant_system.createInt(other.value),
      );
      if (constant is IntConstantValue) {
        return info.newIntValue(constant.intValue);
      }
      return info.unknownValue;
    }
    return -other + this;
  }

  @override
  Value operator -() {
    if (isZero) return this;
    final constant = constant_system.negate.fold(
      constant_system.createInt(value),
    );
    if (constant is IntConstantValue) {
      return info.newIntValue(constant.intValue);
    }
    return info.unknownValue;
  }

  @override
  Value operator &(Value other) {
    if (other is IntValue) {
      final constant =
          constant_system.bitAnd.fold(
                constant_system.createInt(value),
                constant_system.createInt(other.value),
              )
              as IntConstantValue;
      return info.newIntValue(constant.intValue);
    }
    return info.unknownValue;
  }

  @override
  Value min(Value other) {
    if (other is IntValue) {
      return value < other.value ? this : other;
    }
    return other.min(this);
  }

  @override
  Value max(Value other) {
    if (other is IntValue) {
      return value < other.value ? other : this;
    }
    return other.max(this);
  }

  @override
  bool operator ==(other) {
    if (other is! IntValue) return false;
    return value == other.value;
  }

  @override
  int get hashCode => throw UnsupportedError('IntValue.hashCode');

  @override
  String toString() => 'Int($value)';
  @override
  bool get isNegative => value < BigInt.zero;
  @override
  bool get isPositive => value >= BigInt.zero;
  @override
  bool get isZero => value == BigInt.zero;
}

/// The [MaxIntValue] represents the maximum value an integer can have,
/// which is currently +infinity.
class MaxIntValue extends Value {
  MaxIntValue(super.info);
  @override
  Value operator +(Value other) => this;
  @override
  Value operator -(Value other) => this;
  @override
  Value operator -() => info.minIntValue;
  @override
  Value min(Value other) => other;
  @override
  Value max(Value other) => this;
  @override
  String toString() => 'Max';
  @override
  bool get isNegative => false;
  @override
  bool get isPositive => true;
}

/// The [MinIntValue] represents the minimum value an integer can have,
/// which is currently -infinity.
class MinIntValue extends Value {
  MinIntValue(super.info);
  @override
  Value operator +(Value other) => this;
  @override
  Value operator -(Value other) => this;
  @override
  Value operator -() => info.maxIntValue;
  @override
  Value min(Value other) => this;
  @override
  Value max(Value other) => other;
  @override
  String toString() => 'Min';
  @override
  bool get isNegative => true;
  @override
  bool get isPositive => false;
}

/// The [UnknownValue] is the sentinel in our analysis to mark an
/// operation that could not be done because of too much complexity.
class UnknownValue extends Value {
  UnknownValue(super.info);
  @override
  Value operator +(Value other) => info.unknownValue;
  @override
  Value operator -(Value other) => info.unknownValue;
  @override
  Value operator -() => info.unknownValue;
  @override
  Value min(Value other) => info.unknownValue;
  @override
  Value max(Value other) => info.unknownValue;
  @override
  bool get isNegative => false;
  @override
  bool get isPositive => false;
  @override
  String toString() => 'Unknown';
}

abstract class VariableValue extends Value {
  VariableValue(super.info);

  @override
  bool operator ==(other) => throw UnsupportedError('VariableValue.==');

  @override
  int get hashCode => throw UnsupportedError('VariableValue.hashCode');

  @override
  Value operator +(Value other) {
    if (other.isZero) return this;
    if (other is IntValue) {
      if (other.isNegative) {
        return info.newSubtractValue(this, -other);
      }
      return info.newAddValue(this, other);
    }
    if (other is VariableValue) {
      return info.newAddValue(this, other);
    }
    return other + this;
  }

  @override
  Value operator -(Value other) {
    if (other.isZero) return this;
    if (this == other) return info.intZero;
    if (other is IntValue) {
      if (other.isNegative) {
        return info.newAddValue(this, -other);
      }
      return info.newSubtractValue(this, other);
    }
    if (other is VariableValue) {
      return info.newSubtractValue(this, other);
    }
    return -other + this;
  }

  @override
  Value operator -() {
    return info.newNegateValue(this);
  }

  @override
  bool get isNegative => false;
  @override
  bool get isPositive => false;

  @override
  String toString() => throw UnsupportedError('VariableValue.toString');
}

/// The [MarkerValue] class is a symbolc variable used to recognize ranges of
/// loop updates.
class MarkerValue extends VariableValue {
  /// There are two marker values in the marker range - a lower value and an
  /// upper value. [isLower] is true for the lower marker value.
  final bool isLower;
  @override
  final bool isPositive;

  MarkerValue(this.isLower, this.isPositive, super.info);

  @override
  int get hashCode => isLower.hashCode;

  @override
  bool operator ==(other) {
    return other is MarkerValue && isLower == other.isLower;
  }

  @override
  Value replaceMarkers(Value lowerBound, Value upperBound) {
    return isLower ? lowerBound : upperBound;
  }

  @override
  String toString() =>
      'Marker(${isLower ? "lower" : "upper"}${isPositive ? ",>=0" : ""})';
}

/// A symbolic value representing an [HInstruction].
class InstructionValue extends VariableValue {
  final HInstruction instruction;
  InstructionValue(this.instruction, super.info);

  @override
  bool operator ==(other) {
    if (other is! InstructionValue) return false;
    return instruction == other.instruction;
  }

  @override
  int get hashCode => throw UnsupportedError('InstructionValue.hashCode');

  @override
  String toString() => 'Instruction($instruction)';
}

/// Special value for instructions whose type is a positive integer.
class PositiveValue extends InstructionValue {
  PositiveValue(super.instruction, super.info);
  @override
  bool get isPositive => true;
}

/// Represents a binary operation on two [Value]s, where the operation did not
/// yield a canonical value.
abstract class BinaryOperationValue extends Value {
  final Value left;
  final Value right;
  BinaryOperationValue(this.left, this.right, super.info);
}

class AddValue extends BinaryOperationValue {
  AddValue(super.left, super.right, super.info);

  @override
  bool operator ==(other) {
    if (other is! AddValue) return false;
    return (left == other.left && right == other.right) ||
        (left == other.right && right == other.left);
  }

  @override
  int get hashCode => throw UnsupportedError('AddValue.hashCode');

  @override
  Value operator -() => -left - right;

  @override
  Value operator +(Value other) {
    if (other.isZero) return this;
    Value value = left + other;
    if (value != info.unknownValue && value is! BinaryOperationValue) {
      return value + right;
    }
    // If the result is not simple enough, we try the same approach
    // with [right].
    value = right + other;
    if (value != info.unknownValue && value is! BinaryOperationValue) {
      return left + value;
    }
    return info.unknownValue;
  }

  @override
  Value operator -(Value other) {
    if (other.isZero) return this;
    Value value = left - other;
    if (value != info.unknownValue && value is! BinaryOperationValue) {
      return value + right;
    }
    // If the result is not simple enough, we try the same approach
    // with [right].
    value = right - other;
    if (value != info.unknownValue && value is! BinaryOperationValue) {
      return left + value;
    }
    return info.unknownValue;
  }

  @override
  Value replaceMarkers(Value lowerBound, Value upperBound) {
    final newLeft = left.replaceMarkers(lowerBound, upperBound);
    final newRight = right.replaceMarkers(lowerBound, upperBound);
    if (left == newLeft && right == newRight) return this;
    return newLeft + newRight;
  }

  @override
  bool get isNegative => left.isNegative && right.isNegative;
  @override
  bool get isPositive => left.isPositive && right.isPositive;
  @override
  String toString() => '$left + $right';
}

class SubtractValue extends BinaryOperationValue {
  SubtractValue(super.left, super.right, super.info);

  @override
  bool operator ==(other) {
    if (other is! SubtractValue) return false;
    return left == other.left && right == other.right;
  }

  @override
  int get hashCode => throw UnsupportedError('SubtractValue.hashCode');

  @override
  Value operator -() => right - left;

  @override
  Value operator +(Value other) {
    if (other.isZero) return this;
    Value value = left + other;
    if (value != info.unknownValue && value is! BinaryOperationValue) {
      return value - right;
    }
    // If the result is not simple enough, we try the same approach
    // with [right].
    value = other - right;
    if (value != info.unknownValue && value is! BinaryOperationValue) {
      return left + value;
    }
    return info.unknownValue;
  }

  @override
  Value operator -(Value other) {
    if (other.isZero) return this;
    Value value = left - other;
    if (value != info.unknownValue && value is! BinaryOperationValue) {
      return value - right;
    }
    // If the result is not simple enough, we try the same approach
    // with [right].
    value = right + other;
    if (value != info.unknownValue && value is! BinaryOperationValue) {
      return left - value;
    }
    return info.unknownValue;
  }

  @override
  Value replaceMarkers(Value lowerBound, Value upperBound) {
    final newLeft = left.replaceMarkers(lowerBound, upperBound);
    final newRight = right.replaceMarkers(lowerBound, upperBound);
    if (left == newLeft && right == newRight) return this;
    return newLeft - newRight;
  }

  @override
  bool get isNegative => left.isNegative && right.isPositive;
  @override
  bool get isPositive => left.isPositive && right.isNegative;
  @override
  String toString() => '$left - $right';
}

class NegateValue extends Value {
  final Value value;
  NegateValue(this.value, super.info);

  @override
  bool operator ==(other) {
    if (other is! NegateValue) return false;
    return value == other.value;
  }

  @override
  int get hashCode => throw UnsupportedError('Negate.hashCode');

  @override
  Value operator +(other) {
    if (other.isZero) return this;
    if (other == value) return info.intZero;
    if (other is NegateValue) return this - other.value;
    if (other is IntValue) {
      if (other.isNegative) {
        return info.newSubtractValue(this, -other);
      }
      return info.newSubtractValue(other, value);
    }
    if (other is VariableValue) {
      return info.newSubtractValue(other, value);
    }
    return other - value;
  }

  @override
  Value operator &(Value other) => info.unknownValue;

  @override
  Value operator -(other) {
    if (other.isZero) return this;
    if (other is IntValue) {
      if (other.isNegative) {
        return info.newSubtractValue(-other, value);
      }
      return info.newSubtractValue(this, other);
    }
    if (other is VariableValue) {
      return info.newSubtractValue(this, other);
    }
    if (other is NegateValue) return this + other.value;
    return -other - value;
  }

  @override
  Value operator -() => value;

  @override
  Value replaceMarkers(Value lowerBound, Value upperBound) {
    final newValue = value.replaceMarkers(lowerBound, upperBound);
    if (value == newValue) return this;
    return -newValue;
  }

  @override
  bool get isNegative => value.isPositive;
  @override
  bool get isPositive => value.isNegative;
  @override
  String toString() => '-$value';
}

/// A [Range] represents the possible integer values an instruction
/// can have, from its [lower] bound to its [upper] bound, both
/// included.
class Range {
  final Value lower;
  final Value upper;
  final ValueRangeInfo info;
  Range(this.lower, this.upper, this.info) {
    assert(lower != info.unknownValue);
    assert(upper != info.unknownValue);
  }

  Range.unbound(ValueRangeInfo info)
    : this(info.minIntValue, info.maxIntValue, info);

  /// Checks if the given values are unknown, and creates a
  /// range that does not have any unknown values.
  Range.normalize(Value low, Value up, ValueRangeInfo info)
    : this(
        low == info.unknownValue ? info.minIntValue : low,
        up == info.unknownValue ? info.maxIntValue : up,
        info,
      );

  Range union(Range other) {
    return info.newNormalizedRange(
      lower.min(other.lower),
      upper.max(other.upper),
    );
  }

  Range intersection(Range other) {
    Value low = lower.max(other.lower);
    Value up = upper.min(other.upper);
    // If we could not compute max or min, pick a value in the two
    // ranges, with priority to [IntValue]s because they are simpler.
    if (low == info.unknownValue) {
      if (lower is IntValue) {
        low = lower;
      } else if (other.lower is IntValue) {
        low = other.lower;
      } else {
        low = lower;
      }
    }
    if (up == info.unknownValue) {
      if (upper is IntValue) {
        up = upper;
      } else if (other.upper is IntValue) {
        up = other.upper;
      } else {
        up = upper;
      }
    }
    return info.newNormalizedRange(low, up);
  }

  static Range add(Range a, Range b) => a + b;
  static Range subtract(Range a, Range b) => a - b;

  Range operator +(Range other) {
    return info.newNormalizedRange(lower + other.lower, upper + other.upper);
  }

  Range operator -(Range other) {
    return info.newNormalizedRange(lower - other.upper, upper - other.lower);
  }

  Range operator -() {
    return info.newNormalizedRange(-upper, -lower);
  }

  Range operator &(Range other) {
    if (isSingleValue &&
        other.isSingleValue &&
        lower is IntValue &&
        other.lower is IntValue) {
      return info.newNormalizedRange(lower & other.lower, upper & other.upper);
    }
    if (isPositive && other.isPositive) {
      Value up = upper.min(other.upper);
      if (up == info.unknownValue) {
        // If we could not find a trivial bound, just try to use the
        // one that is an int.
        up = upper is IntValue ? upper : other.upper;
        // Make sure we get the same upper bound, whether it's a & b
        // or b & a.
        if (up is! IntValue && upper != other.upper) up = info.maxIntValue;
      }
      return info.newNormalizedRange(info.intZero, up);
    } else if (isPositive) {
      return info.newNormalizedRange(info.intZero, upper);
    } else if (other.isPositive) {
      return info.newNormalizedRange(info.intZero, other.upper);
    } else {
      return info.newUnboundRange();
    }
  }

  Range replaceMarkers(Value lowerBound, Value upperBound) {
    final newLower = lower.replaceMarkers(lowerBound, upperBound);
    final newUpper = upper.replaceMarkers(lowerBound, upperBound);
    if (lower == newLower && upper == newUpper) return this;
    return info.newNormalizedRange(newLower, newUpper);
  }

  @override
  bool operator ==(other) {
    if (other is! Range) return false;
    return other.lower == lower && other.upper == upper;
  }

  @override
  int get hashCode => throw UnsupportedError('Range.hashCode');

  bool operator <(Range other) {
    return upper != other.lower && upper.min(other.lower) == upper;
  }

  bool operator >(Range other) {
    return lower != other.upper && lower.max(other.upper) == lower;
  }

  bool operator <=(Range other) {
    return upper.min(other.lower) == upper;
  }

  bool operator >=(Range other) {
    return lower.max(other.upper) == lower;
  }

  bool get isNegative => upper.isNegative;
  bool get isPositive => lower.isPositive;
  bool get isSingleValue => lower == upper;

  @override
  String toString() => '[$lower, $upper]';
}

typedef BinaryRangeOperation = Range Function(Range, Range);

/// Visits the graph in dominator order, and computes value ranges for
/// integer instructions. While visiting the graph, this phase also
/// removes unnecessary bounds checks, and comparisons that are proven
/// to be true or false.
class SsaValueRangeAnalyzer extends HBaseVisitor<Range>
    implements OptimizationPhase {
  @override
  String get name => 'SsaValueRangeAnalyzer';

  /// List of [HRangeConversion] instructions created by the phase. We
  /// save them here in order to remove them once the phase is done.
  final List<HRangeConversion> conversions = [];

  /// List of [HBoundsCheck] instructions collected during visit.
  final List<HBoundsCheck> boundsChecks = [];

  /// Value ranges for integer instructions. This map gets populated by
  /// the dominator tree visit.
  final Map<HInstruction, Range> ranges = {};

  final JClosedWorld closedWorld;
  final ValueRangeInfo info = ValueRangeInfo();
  final SsaOptimizerWorkItem workItem;
  final Tracer tracer;

  late HGraph graph;

  SsaValueRangeAnalyzer(this.closedWorld, this.workItem, this.tracer);

  @override
  void visitGraph(HGraph graph) {
    // Example debugging code:
    //
    //    _DEBUG = graph.element.toString().contains('(main)');

    this.graph = graph;
    visitDominatorTree(graph);

    tracer.traceGraph('$name.analysis', graph);

    optimizeBoundsChecks();

    // We remove the range conversions after visiting the graph so
    // that the graph does not get polluted with these instructions
    // only necessary for this phase.
    removeRangeConversion();

    // TODO(herhut): Find a cleaner way to pass around ranges.
    workItem.ranges = ranges;
  }

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

  void optimizeBoundsChecks() {
    for (final check in boundsChecks) {
      if (check.staticChecks == StaticBoundsChecks.alwaysTrue) {
        final block = check.block!;
        block.rewrite(check, check.index);
        block.remove(check);
      }
    }
  }

  void removeRangeConversion() {
    for (final instruction in conversions) {
      final block = instruction.block!;
      block.rewrite(instruction, instruction.inputs[0]);
      block.remove(instruction);
    }
  }

  @override
  void visitBasicBlock(HBasicBlock node) {
    void visit(HInstruction instruction) {
      Range range = instruction.accept(this);
      if (instruction is! HControlFlow &&
          instruction
              .isInteger(closedWorld.abstractValueDomain)
              .isDefinitelyTrue) {
        ranges[instruction] = range;
      }
    }

    node.forEachPhi(visit);
    node.forEachInstruction(visit);
  }

  @override
  Range visitInstruction(HInstruction instruction) {
    if (instruction
        .isPositiveInteger(closedWorld.abstractValueDomain)
        .isDefinitelyTrue) {
      return info.newNormalizedRange(
        info.intZero,
        info.newPositiveValue(instruction),
      );
    } else if (instruction
        .isInteger(closedWorld.abstractValueDomain)
        .isDefinitelyTrue) {
      InstructionValue value = info.newInstructionValue(instruction);
      return info.newNormalizedRange(value, value);
    } else {
      return info.newUnboundRange();
    }
  }

  @override
  Range visitControlFlow(HControlFlow node) {
    return info.newUnboundRange();
  }

  @override
  Range visitPhi(HPhi node) {
    if (node.isInteger(closedWorld.abstractValueDomain).isPotentiallyFalse) {
      return info.newUnboundRange();
    }
    // Some phases may replace instructions that change the inputs of
    // this phi. Only the [SsaTypesPropagation] phase will update the
    // phi type. Play it safe by assuming the [SsaTypesPropagation]
    // phase is not necessarily run before the [ValueRangeAnalyzer].
    if (node.inputs.any(
      (i) => i.isInteger(closedWorld.abstractValueDomain).isPotentiallyFalse,
    )) {
      return info.newUnboundRange();
    }
    if (node.block!.isLoopHeader()) {
      final range = LoopUpdateRecognizer(
        closedWorld,
        UnmodifiableMapView(ranges),
        info,
      ).run(node);
      if (range == null) return info.newUnboundRange();
      return range;
    }

    Range range = ranges[node.inputs[0]]!;
    for (int i = 1; i < node.inputs.length; i++) {
      range = range.union(ranges[node.inputs[i]]!);
    }
    return range;
  }

  @override
  Range visitConstant(HConstant node) {
    ConstantValue constant = node.constant;
    if (constant is DeferredGlobalConstantValue) {
      constant = constant.referenced;
    }
    if (constant is! IntConstantValue ||
        node.isInteger(closedWorld.abstractValueDomain).isPotentiallyFalse) {
      return info.newUnboundRange();
    }
    NumConstantValue constantNum = constant;
    if (constantNum.isPositiveInfinity || constantNum.isNegativeInfinity) {
      return info.newUnboundRange();
    }
    if (constantNum.isMinusZero) {
      constantNum = IntConstantValue(BigInt.zero);
    }

    BigInt intValue = constantNum is IntConstantValue
        ? constantNum.intValue
        : BigInt.from(constantNum.doubleValue.toInt());
    Value value = info.newIntValue(intValue);
    return info.newNormalizedRange(value, value);
  }

  @override
  Range visitFieldGet(HFieldGet node) {
    return visitInstruction(node);
  }

  @override
  Range visitGetLength(HGetLength node) {
    PositiveValue value = info.newPositiveValue(node);
    // We know this range is above zero. To simplify the analysis, we
    // put the zero value as the lower bound of this range. This
    // allows to easily remove the second bound check in the following
    // expression: a[1] + a[0].
    return info.newNormalizedRange(info.intZero, value);
  }

  @override
  Range visitBoundsCheck(HBoundsCheck node) {
    boundsChecks.add(node);
    // Save the next instruction, in case the check gets removed.
    final next = node.next;
    Range? indexRange = ranges[node.index];
    final lengthRange = ranges[node.length];
    if (indexRange == null) {
      indexRange = info.newUnboundRange();
      assert(
        node.index
            .isInteger(closedWorld.abstractValueDomain)
            .isPotentiallyFalse,
      );
    }
    if (lengthRange == null) {
      // We might have lost the length range due to a type conversion that
      // asserts a non-integer type. In such a case, the program will never
      // get to this point anyway, so no need to try and refine ranges.
      return indexRange;
    }
    assert(
      node.length.isInteger(closedWorld.abstractValueDomain).isDefinitelyTrue,
    );

    // Check if the index is strictly below the upper bound of the length
    // range.
    Value maxIndex = lengthRange.upper - info.intOne;
    bool belowLength =
        maxIndex != info.maxIntValue &&
        indexRange.upper.min(maxIndex) == indexRange.upper;

    // Check if the index is strictly below the lower bound of the length
    // range.
    belowLength =
        belowLength ||
        (indexRange.upper != lengthRange.lower &&
            indexRange.upper.min(lengthRange.lower) == indexRange.upper);
    if (indexRange.isPositive && belowLength) {
      node.staticChecks = StaticBoundsChecks.alwaysTrue;
    } else if (indexRange.isNegative || lengthRange < indexRange) {
      node.staticChecks = StaticBoundsChecks.alwaysFalse;
      // The check is always false, and whatever instruction it
      // dominates is dead code.
      return indexRange;
    } else if (indexRange.isPositive) {
      node.staticChecks = StaticBoundsChecks.alwaysAboveZero;
    } else if (belowLength) {
      node.staticChecks = StaticBoundsChecks.alwaysBelowLength;
    }

    if (indexRange.isPositive) {
      // If the test passes, we know the lower bound of the length is
      // greater or equal than the lower bound of the index.
      Value low = lengthRange.lower.max(indexRange.lower);
      if (low != info.unknownValue && node.length is! HConstant) {
        HInstruction instruction = createRangeConversion(next!, node.length);
        ranges[instruction] = info.newNormalizedRange(low, lengthRange.upper);
      }
    }

    // Update the range of the index if using the maximum index
    // narrows it. Use that new range for this instruction as well.
    Range newIndexRange = indexRange.intersection(
      info.newNormalizedRange(info.intZero, maxIndex),
    );
    if (indexRange == newIndexRange) return indexRange;
    // Explicitly attach the range information to the index instruction,
    // which may be used by other instructions.  Returning the new range will
    // attach it to this instruction.
    HInstruction instruction = createRangeConversion(next!, node.index);
    ranges[instruction] = newIndexRange;
    return newIndexRange;
  }

  @override
  Range visitRelational(HRelational node) {
    HInstruction right = node.right;
    HInstruction left = node.left;
    if (left.isInteger(closedWorld.abstractValueDomain).isPotentiallyFalse) {
      return info.newUnboundRange();
    }
    if (right.isInteger(closedWorld.abstractValueDomain).isPotentiallyFalse) {
      return info.newUnboundRange();
    }
    constant_system.BinaryOperation operation = node.operation();
    Range rightRange = ranges[node.right]!;
    Range leftRange = ranges[node.left]!;

    if (node is HIdentity) {
      handleEqualityCheck(node);
    } else if (applyRelationalOperation(operation, leftRange, rightRange)) {
      final block = node.block!;
      block.rewrite(node, graph.addConstantBool(true, closedWorld));
      block.remove(node);
    } else if (applyRelationalOperation(
      negateOperation(operation),
      leftRange,
      rightRange,
    )) {
      final block = node.block!;
      block.rewrite(node, graph.addConstantBool(false, closedWorld));
      block.remove(node);
    }
    return info.newUnboundRange();
  }

  bool applyRelationalOperation(
    constant_system.BinaryOperation operation,
    Range left,
    Range right,
  ) {
    if (operation == const constant_system.LessOperation()) {
      return left < right;
    }
    if (operation == const constant_system.LessEqualOperation()) {
      return left <= right;
    }
    if (operation == const constant_system.GreaterOperation()) {
      return left > right;
    }
    if (operation == const constant_system.GreaterEqualOperation()) {
      return left >= right;
    }

    throw StateError('Unknown relational operation: $operation, $left, $right');
  }

  void handleEqualityCheck(HRelational node) {
    Range right = ranges[node.right]!;
    Range left = ranges[node.left]!;
    if (left.isSingleValue && right.isSingleValue && left == right) {
      final block = node.block!;
      block.rewrite(node, graph.addConstantBool(true, closedWorld));
      block.remove(node);
    }
  }

  Range handleInvokeModulo(HInvokeDynamicMethod invoke) {
    HInstruction left = invoke.inputs[1];
    HInstruction right = invoke.inputs[2];
    final divisor = ranges[right];
    if (divisor != null) {
      // For Integer values we can be precise in the upper bound, so special
      // case those.
      if (left.isInteger(closedWorld.abstractValueDomain).isDefinitelyTrue &&
          right.isInteger(closedWorld.abstractValueDomain).isDefinitelyTrue) {
        if (divisor.isPositive) {
          return info.newNormalizedRange(
            info.intZero,
            divisor.upper - info.intOne,
          );
        } else if (divisor.isNegative) {
          return info.newNormalizedRange(
            info.intZero,
            info.newNegateValue(divisor.lower) - info.intOne,
          );
        }
      } else if (left
              .isNumber(closedWorld.abstractValueDomain)
              .isDefinitelyTrue &&
          right.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue) {
        if (divisor.isPositive) {
          return info.newNormalizedRange(info.intZero, divisor.upper);
        } else if (divisor.isNegative) {
          return info.newNormalizedRange(
            info.intZero,
            info.newNegateValue(divisor.lower),
          );
        }
      }
    }
    return info.newUnboundRange();
  }

  @override
  Range visitRemainder(HRemainder node) {
    HInstruction left = node.inputs[0];
    HInstruction right = node.inputs[1];
    final dividend = ranges[left];
    // If both operands are >=0, the result is >= 0 and bounded by the divisor.
    if ((dividend != null && dividend.isPositive) ||
        left
            .isPositiveInteger(closedWorld.abstractValueDomain)
            .isDefinitelyTrue) {
      final divisor = ranges[right];
      if (divisor != null) {
        if (divisor.isPositive) {
          // For Integer values we can be precise in the upper bound.
          if (left
                  .isInteger(closedWorld.abstractValueDomain)
                  .isDefinitelyTrue &&
              right
                  .isInteger(closedWorld.abstractValueDomain)
                  .isDefinitelyTrue) {
            return info.newNormalizedRange(
              info.intZero,
              divisor.upper - info.intOne,
            );
          }
          if (left.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue &&
              right
                  .isNumber(closedWorld.abstractValueDomain)
                  .isDefinitelyTrue) {
            return info.newNormalizedRange(info.intZero, divisor.upper);
          }
        }
      }
    }
    return info.newUnboundRange();
  }

  @override
  Range visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
    if ((node.inputs.length == 3) && (node.selector.name == "%")) {
      return handleInvokeModulo(node);
    }
    return super.visitInvokeDynamicMethod(node);
  }

  Range handleBinaryOperation(
    HBinaryArithmetic instruction,
    BinaryRangeOperation operation,
  ) {
    if (instruction
        .isInteger(closedWorld.abstractValueDomain)
        .isPotentiallyFalse) {
      return info.newUnboundRange();
    }
    return operation(ranges[instruction.left]!, ranges[instruction.right]!);
  }

  @override
  Range visitAdd(HAdd node) {
    return handleBinaryOperation(node, Range.add);
  }

  @override
  Range visitSubtract(HSubtract node) {
    return handleBinaryOperation(node, Range.subtract);
  }

  @override
  Range visitBitAnd(HBitAnd node) {
    if (node.isInteger(closedWorld.abstractValueDomain).isPotentiallyFalse) {
      return info.newUnboundRange();
    }
    HInstruction right = node.right;
    HInstruction left = node.left;
    if (left.isInteger(closedWorld.abstractValueDomain).isDefinitelyTrue &&
        right.isInteger(closedWorld.abstractValueDomain).isDefinitelyTrue) {
      return ranges[left]! & ranges[right]!;
    }

    Range tryComputeRange(HInstruction instruction) {
      final range = ranges[instruction]!;
      if (range.isPositive) {
        return info.newNormalizedRange(info.intZero, range.upper);
      } else if (range.isNegative) {
        return info.newNormalizedRange(range.lower, info.intZero);
      }
      return info.newUnboundRange();
    }

    if (left.isInteger(closedWorld.abstractValueDomain).isDefinitelyTrue) {
      return tryComputeRange(left);
    }
    if (right.isInteger(closedWorld.abstractValueDomain).isDefinitelyTrue) {
      return tryComputeRange(right);
    }
    return info.newUnboundRange();
  }

  @override
  Range visitCheck(HCheck node) {
    final range = ranges[node.checkedInput];
    return range ?? visitInstruction(node);
  }

  HInstruction createRangeConversion(
    HInstruction cursor,
    HInstruction instruction,
  ) {
    HRangeConversion newInstruction = HRangeConversion(
      instruction,
      closedWorld.abstractValueDomain.intType,
    );
    conversions.add(newInstruction);
    cursor.block!.addBefore(cursor, newInstruction);
    // Update the users of the instruction dominated by [cursor] to
    // use the new instruction, that has an narrower range.
    instruction.replaceAllUsersDominatedBy(cursor, newInstruction);
    return newInstruction;
  }

  static constant_system.BinaryOperation negateOperation(
    constant_system.BinaryOperation operation,
  ) {
    if (operation == const constant_system.LessOperation()) {
      return const constant_system.GreaterEqualOperation();
    } else if (operation == const constant_system.LessEqualOperation()) {
      return const constant_system.GreaterOperation();
    } else if (operation == const constant_system.GreaterOperation()) {
      return const constant_system.LessEqualOperation();
    } else if (operation == const constant_system.GreaterEqualOperation()) {
      return const constant_system.LessOperation();
    }
    throw ArgumentError('Cannot negate $operation');
  }

  static constant_system.BinaryOperation? flipOperation(
    constant_system.BinaryOperation operation,
  ) {
    if (operation == const constant_system.LessOperation()) {
      return const constant_system.GreaterOperation();
    } else if (operation == const constant_system.LessEqualOperation()) {
      return const constant_system.GreaterEqualOperation();
    } else if (operation == const constant_system.GreaterOperation()) {
      return const constant_system.LessOperation();
    } else if (operation == const constant_system.GreaterEqualOperation()) {
      return const constant_system.LessEqualOperation();
    } else {
      return null;
    }
  }

  Range computeConstrainedRange(
    constant_system.BinaryOperation operation,
    Range leftRange,
    Range rightRange,
  ) {
    Range range;
    if (operation == const constant_system.LessOperation()) {
      range = info.newNormalizedRange(
        info.minIntValue,
        rightRange.upper - info.intOne,
      );
    } else if (operation == const constant_system.LessEqualOperation()) {
      range = info.newNormalizedRange(info.minIntValue, rightRange.upper);
    } else if (operation == const constant_system.GreaterOperation()) {
      range = info.newNormalizedRange(
        rightRange.lower + info.intOne,
        info.maxIntValue,
      );
    } else if (operation == const constant_system.GreaterEqualOperation()) {
      range = info.newNormalizedRange(rightRange.lower, info.maxIntValue);
    } else {
      range = info.newUnboundRange();
    }
    return range.intersection(leftRange);
  }

  @override
  Range visitConditionalBranch(HConditionalBranch node) {
    HInstruction condition = node.condition;
    // TODO(ngeoffray): Handle complex conditions.
    if (condition is HRelational) {
      if (condition is HIdentity) return info.newUnboundRange();
      HInstruction right = condition.right;
      HInstruction left = condition.left;
      if (left.isInteger(closedWorld.abstractValueDomain).isPotentiallyFalse) {
        return info.newUnboundRange();
      }
      if (right.isInteger(closedWorld.abstractValueDomain).isPotentiallyFalse) {
        return info.newUnboundRange();
      }

      final rightRange = ranges[right]!;
      final leftRange = ranges[left]!;
      constant_system.BinaryOperation operation = condition.operation();
      constant_system.BinaryOperation mirrorOp = flipOperation(operation)!;
      // Only update the true branch if this block is the only
      // predecessor.
      if (node.trueBranch.predecessors.length == 1) {
        assert(node.trueBranch.predecessors[0] == node.block);
        // Update the true branch to use narrower ranges for [left] and
        // [right].
        Range range = computeConstrainedRange(operation, leftRange, rightRange);
        if (leftRange != range) {
          HInstruction instruction = createRangeConversion(
            node.trueBranch.first!,
            left,
          );
          ranges[instruction] = range;
        }

        range = computeConstrainedRange(mirrorOp, rightRange, leftRange);
        if (rightRange != range) {
          HInstruction instruction = createRangeConversion(
            node.trueBranch.first!,
            right,
          );
          ranges[instruction] = range;
        }
      }

      // Only update the false branch if this block is the only
      // predecessor.
      if (node.falseBranch.predecessors.length == 1) {
        assert(node.falseBranch.predecessors[0] == node.block);
        constant_system.BinaryOperation reverse = negateOperation(operation);
        constant_system.BinaryOperation reversedMirror = flipOperation(
          reverse,
        )!;
        // Update the false branch to use narrower ranges for [left] and
        // [right].
        Range range = computeConstrainedRange(reverse, leftRange, rightRange);
        if (leftRange != range) {
          HInstruction instruction = createRangeConversion(
            node.falseBranch.first!,
            left,
          );
          ranges[instruction] = range;
        }

        range = computeConstrainedRange(reversedMirror, rightRange, leftRange);
        if (rightRange != range) {
          HInstruction instruction = createRangeConversion(
            node.falseBranch.first!,
            right,
          );
          ranges[instruction] = range;
        }
      }

      return info.newUnboundRange();
    }
    return info.newUnboundRange();
  }

  @override
  Range visitRangeConversion(HRangeConversion node) {
    return ranges[node]!;
  }
}

/// Tries to find a range for the update instruction of a loop phi.
class LoopUpdateRecognizer extends HBaseVisitor<Range?> {
  final JClosedWorld closedWorld;
  // Ranges from outside the loop, which never contain a marker value.
  final UnmodifiableMapView<HInstruction, Range> ranges;
  final ValueRangeInfo info;

  // Ranges inside the loop which may contain marker values specific to the loop
  // phi.
  final Map<HInstruction, Range?> temporaryRanges = {};

  LoopUpdateRecognizer(this.closedWorld, this.ranges, this.info);

  Range? run(HPhi loopPhi) {
    // Create a marker range for the loop phi. This is the symbolic initial
    // value of the loop variable for one iteration.
    bool isPositive = loopPhi
        .isPositiveInteger(closedWorld.abstractValueDomain)
        .isDefinitelyTrue;
    final lowerMarker = info.newMarkerValue(
      isLower: true,
      isPositive: isPositive,
    );
    final upperMarker = info.newMarkerValue(
      isLower: false,
      isPositive: isPositive,
    );
    final markerRange = info.newNormalizedRange(lowerMarker, upperMarker);

    // Compute the update range as a function of the initial marker range.
    temporaryRanges[loopPhi] = markerRange;
    final updateRange = visit(loopPhi.inputs[1]);
    if (updateRange == null) return null;

    // Use 'union' to compare the marker with the loop update to find out if the
    // lower or upper value did not change.
    final deltaRange = markerRange.union(updateRange);

    // If the lower (respectively upper) value is the marker, we know the loop
    // does not change it, so we can use the [startRange]'s lower (upper) value.
    // Otherwise the lower (upper) value changes and needs to be widened to the
    // minimum (maximum) value.
    final startRange = ranges[loopPhi.inputs[0]]!;

    Value lowerLimit = isPositive ? info.intZero : info.minIntValue;
    Value upperLimit = info.maxIntValue;
    Value lowerBound = deltaRange.lower == lowerMarker
        ? startRange.lower
        : lowerLimit;
    Value upperBound = deltaRange.upper == upperMarker
        ? startRange.upper
        : upperLimit;

    // Widen the update range and union with the start range.
    final widened = updateRange.replaceMarkers(lowerBound, upperBound);
    final result = startRange.union(widened);

    if (_debug) {
      print(
        '------- ${loopPhi.sourceElement}'
        '\n    marker  $markerRange'
        '\n    update  $updateRange'
        '\n    delta   $deltaRange'
        '\n    start   $startRange'
        '\n    widened $widened'
        '\n    result= $result',
      );
    }

    return result;
  }

  Range? visit(HInstruction instruction) {
    if (instruction
        .isInteger(closedWorld.abstractValueDomain)
        .isPotentiallyFalse) {
      return null;
    }
    Range? result = ranges[instruction];
    if (result != null) return result;
    return temporaryRanges[instruction] ??= instruction.accept(this);
  }

  @override
  Range? visitPhi(HPhi node) {
    // If the update of a loop phi involves another loop phi, we give up.
    if (node.block!.isLoopHeader()) return null;
    Range? phiRange;
    for (HInstruction input in node.inputs) {
      final inputRange = visit(input);
      if (inputRange == null) return null;
      if (phiRange == null) {
        phiRange = inputRange;
      } else {
        phiRange = phiRange.union(inputRange);
      }
    }
    return phiRange;
  }

  @override
  Range? visitCheck(HCheck node) {
    return visit(node.checkedInput);
  }

  @override
  Range? visitAdd(HAdd node) {
    return handleBinaryOperation(node, Range.add);
  }

  @override
  Range? visitSubtract(HSubtract node) {
    return handleBinaryOperation(node, Range.subtract);
  }

  Range? handleBinaryOperation(
    HBinaryArithmetic instruction,
    BinaryRangeOperation operation,
  ) {
    final leftRange = visit(instruction.left);
    final rightRange = visit(instruction.right);
    if (leftRange == null || rightRange == null) return null;
    return operation(leftRange, rightRange);
  }
}
