// Copyright (c) 2018, the R8 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.
package com.android.tools.r8.ir.optimize;

import static com.android.tools.r8.ir.analysis.type.Nullability.definitelyNotNull;
import static com.google.common.base.Predicates.alwaysTrue;

import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClassAndField;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.FieldResolutionResult.SuccessfulFieldResolutionResult;
import com.android.tools.r8.graph.MethodResolutionResult.SingleResolutionResult;
import com.android.tools.r8.ir.analysis.type.DynamicType;
import com.android.tools.r8.ir.analysis.type.DynamicTypeWithUpperBound;
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Assume;
import com.android.tools.r8.ir.code.Assume.DynamicTypeAssumption;
import com.android.tools.r8.ir.code.Assume.NonNullAssumption;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.BasicBlockIterator;
import com.android.tools.r8.ir.code.ConstNumber;
import com.android.tools.r8.ir.code.DominatorTree;
import com.android.tools.r8.ir.code.FieldInstruction;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.If;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InstructionIterator;
import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.code.LazyDominatorTree;
import com.android.tools.r8.ir.code.Phi;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.optimize.info.FieldOptimizationInfo;
import com.android.tools.r8.ir.optimize.info.MethodOptimizationInfo;
import com.android.tools.r8.ir.optimize.membervaluepropagation.assume.AssumeInfo;
import com.android.tools.r8.ir.optimize.membervaluepropagation.assume.AssumeInfoLookup;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.utils.TriConsumer;
import com.android.tools.r8.utils.TriFunction;
import com.android.tools.r8.utils.TriPredicate;
import com.google.common.collect.Sets;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.ints.IntListIterator;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;

public class AssumeInserter {

  private final AppView<AppInfoWithLiveness> appView;

  public AssumeInserter(AppView<AppInfoWithLiveness> appView) {
    this.appView = appView;
  }

  public void insertAssumeInstructions(IRCode code, Timing timing) {
    insertAssumeInstructionsInBlocks(code, code.listIterator(), alwaysTrue(), timing);
  }

  public void insertAssumeInstructionsInBlocks(
      IRCode code,
      BasicBlockIterator blockIterator,
      Predicate<BasicBlock> blockTester,
      Timing timing) {
    timing.begin("Insert assume instructions");
    internalInsertAssumeInstructionsInBlocks(code, blockIterator, blockTester, timing);
    timing.end();
  }

  private void internalInsertAssumeInstructionsInBlocks(
      IRCode code,
      BasicBlockIterator blockIterator,
      Predicate<BasicBlock> blockTester,
      Timing timing) {
    timing.begin("Part 1: Compute assumed values");
    AssumedValues assumedValues = computeAssumedValues(code, blockIterator, blockTester);
    timing.end();
    if (assumedValues.isEmpty()) {
      return;
    }

    timing.begin("Part 2: Remove redundant assume instructions");
    removeRedundantAssumeInstructions(assumedValues);
    timing.end();

    timing.begin("Part 3: Compute dominated users");
    Map<Instruction, Map<Value, AssumedValueInfo>> redundantAssumedValues =
        computeDominanceForAssumedValues(code, assumedValues);
    timing.end();
    if (assumedValues.isEmpty()) {
      return;
    }

    timing.begin("Part 4: Remove redundant dominated assume instructions");
    removeRedundantDominatedAssumeInstructions(assumedValues, redundantAssumedValues);
    timing.end();
    if (assumedValues.isEmpty()) {
      return;
    }

    timing.begin("Part 5: Materialize assume instructions");
    materializeAssumeInstructions(code, assumedValues);
    timing.end();
  }

  private AssumedValues computeAssumedValues(
      IRCode code, BasicBlockIterator blockIterator, Predicate<BasicBlock> blockTester) {
    AssumedValues.Builder assumedValuesBuilder = new AssumedValues.Builder();
    while (blockIterator.hasNext()) {
      BasicBlock block = blockIterator.next();
      if (blockTester.test(block)) {
        computeAssumedValuesInBlock(code, blockIterator, block, assumedValuesBuilder);
      }
    }
    return assumedValuesBuilder.build();
  }

  private void computeAssumedValuesInBlock(
      IRCode code,
      BasicBlockIterator blockIterator,
      BasicBlock block,
      AssumedValues.Builder assumedValuesBuilder) {
    // Add non-null after
    // 1) instructions that implicitly indicate receiver/array is not null.
    // 2) invocations that are guaranteed to return a non-null value.
    // 3) parameters that are not null after the invocation.
    // 4) field-get instructions that are guaranteed to read a non-null value.
    InstructionListIterator instructionIterator = block.listIterator(code);
    while (instructionIterator.hasNext()) {
      Instruction current = instructionIterator.next();
      boolean needsAssumeInstruction = false;

      // Case (1), instructions that implicitly indicate receiver/array is not null.
      if (current.throwsOnNullInput()) {
        Value inValue = current.getNonNullInput();
        if (assumedValuesBuilder.isMaybeNull(inValue)
            && isNullableReferenceTypeWithOtherNonDebugUsers(inValue, current)) {
          assumedValuesBuilder.addNonNullValueWithUnknownDominance(current, inValue);
          needsAssumeInstruction = true;
        }
      }

      if (current.isInvokeMethod()) {
        // Case (2) and (3).
        needsAssumeInstruction |=
            computeAssumedValuesForInvokeMethod(
                code, current.asInvokeMethod(), assumedValuesBuilder);
      } else if (current.isFieldGet()) {
        // Case (4), field-get instructions that are guaranteed to read a non-null value.
        needsAssumeInstruction |=
            computeAssumedValuesForFieldGet(current.asFieldInstruction(), assumedValuesBuilder);
      }

      // If we need to insert an assume instruction into a block with catch handlers, we split the
      // block such that the IR is ready for the insertion of the assume instruction.
      //
      // This splitting could in principle be deferred until we materialize the assume instructions,
      // but then we would need to rewind the basic block iterator to the beginning, and scan over
      // the instructions another time, splitting the blocks as needed.
      if (block.hasCatchHandlers()) {
        if (needsAssumeInstruction) {
          BasicBlock insertionBlock = instructionIterator.split(code, blockIterator);
          assert !instructionIterator.hasNext();
          assert instructionIterator.peekPrevious().isGoto();
          assert blockIterator.peekPrevious() == insertionBlock;
          computeAssumedValuesInBlock(code, blockIterator, insertionBlock, assumedValuesBuilder);
          return;
        }
        if (current.instructionTypeCanThrow()) {
          break;
        }
      }
    }

    If ifInstruction = block.exit().asIf();
    if (ifInstruction != null && ifInstruction.isNonTrivialNullTest()) {
      Value lhs = ifInstruction.lhs();
      if (assumedValuesBuilder.isMaybeNull(lhs)
          && isNullableReferenceTypeWithOtherNonDebugUsers(lhs, ifInstruction)
          && ifInstruction.targetFromNonNullObject().getPredecessors().size() == 1) {
        assumedValuesBuilder.addNonNullValueWithUnknownDominance(ifInstruction, lhs);
      }
    }
  }

  private boolean computeAssumedValuesForInvokeMethod(
      IRCode code, InvokeMethod invoke, AssumedValues.Builder assumedValuesBuilder) {
    if (!invoke.hasOutValue() && invoke.getInvokedMethod().proto.parameters.isEmpty()) {
      return false;
    }

    DexMethod invokedMethod = invoke.getInvokedMethod();
    if (invokedMethod.holder.isArrayType()
        && invokedMethod.match(appView.dexItemFactory().objectMembers.clone)) {
      return computeAssumedValuesFromArrayClone(invoke, assumedValuesBuilder);
    }

    return computeAssumedValuesFromSingleTarget(code, invoke, assumedValuesBuilder);
  }

  private boolean computeAssumedValuesFromArrayClone(
      InvokeMethod invoke, AssumedValues.Builder assumedValuesBuilder) {
    Value outValue = invoke.outValue();
    if (outValue == null || !outValue.hasNonDebugUsers()) {
      return false;
    }

    DynamicTypeWithUpperBound dynamicType =
        invoke.getInvokedMethod().getHolderType().toDynamicType(appView, definitelyNotNull());
    assumedValuesBuilder.addAssumedValueKnownToDominateAllUsers(invoke, outValue, dynamicType);
    return true;
  }

  private boolean computeAssumedValuesFromSingleTarget(
      IRCode code, InvokeMethod invoke, AssumedValues.Builder assumedValuesBuilder) {
    SingleResolutionResult resolutionResult =
        appView
            .appInfo()
            .unsafeResolveMethodDueToDexFormat(invoke.getInvokedMethod())
            .asSingleResolution();
    if (resolutionResult == null) {
      return false;
    }

    DexClassAndMethod singleTarget = invoke.lookupSingleTarget(appView, code.context());
    if (invoke.hasUsedOutValue() && invoke.getOutType().isReferenceType()) {
      AssumeInfo assumeInfo =
          AssumeInfoLookup.lookupAssumeInfo(appView, resolutionResult, singleTarget);
      if (assumeInfo != null
          && assumeInfo.hasReturnInfo()
          && assumeInfo.getReturnInfo().isNonNull()) {
        assumedValuesBuilder.addNonNullValueKnownToDominateAllUsers(invoke, invoke.outValue());
      }
    }

    if (singleTarget == null) {
      return false;
    }

    boolean needsAssumeInstruction = false;
    MethodOptimizationInfo optimizationInfo = singleTarget.getDefinition().getOptimizationInfo();

    // Case (2), invocations that are guaranteed to return a non-null value.
    if (invoke.hasUsedOutValue()) {
      needsAssumeInstruction =
          computeAssumedValuesForOutValue(
              invoke, optimizationInfo.getDynamicType(), assumedValuesBuilder);
    }

    // Case (3), parameters that are not null after the invocation.
    BitSet nonNullParamOnNormalExits = optimizationInfo.getNonNullParamOnNormalExits();
    if (nonNullParamOnNormalExits != null) {
      int start = invoke.isInvokeMethodWithReceiver() ? 1 : 0;
      for (int i = start; i < invoke.arguments().size(); i++) {
        if (nonNullParamOnNormalExits.get(i)) {
          Value argument = invoke.getArgument(i);
          if (assumedValuesBuilder.isMaybeNull(argument)
              && isNullableReferenceTypeWithOtherNonDebugUsers(argument, invoke)) {
            assumedValuesBuilder.addNonNullValueWithUnknownDominance(invoke, argument);
            needsAssumeInstruction = true;
          }
        }
      }
    }
    return needsAssumeInstruction;
  }

  private boolean computeAssumedValuesForFieldGet(
      FieldInstruction fieldGet, AssumedValues.Builder assumedValuesBuilder) {
    if (fieldGet.hasUnusedOutValue()) {
      return false;
    }

    SuccessfulFieldResolutionResult resolutionResult =
        appView.appInfo().resolveField(fieldGet.getField()).asSuccessfulResolution();
    if (resolutionResult == null) {
      return false;
    }

    DexClassAndField field = resolutionResult.getResolutionPair();

    if (field.getType().isReferenceType()) {
      AssumeInfo assumeInfo = AssumeInfoLookup.lookupAssumeInfo(appView, field);
      if (assumeInfo != null
          && assumeInfo.hasReturnInfo()
          && assumeInfo.getReturnInfo().isNonNull()) {
        assumedValuesBuilder.addNonNullValueKnownToDominateAllUsers(fieldGet, fieldGet.outValue());
      }
    }

    FieldOptimizationInfo optimizationInfo = field.getDefinition().getOptimizationInfo();
    return computeAssumedValuesForOutValue(
        fieldGet, optimizationInfo.getDynamicType(), assumedValuesBuilder);
  }

  private boolean computeAssumedValuesForOutValue(
      Instruction instruction,
      DynamicType dynamicType,
      AssumedValues.Builder assumedValuesBuilder) {
    Value outValue = instruction.outValue();
    // Do not insert dynamic type information if it does not refine the static type.
    if (dynamicType.isUnknown()) {
      return false;
    }

    // Insert an assume-not-null instruction if the dynamic type only refines the nullability.
    if (dynamicType.isNotNullType()) {
      assumedValuesBuilder.addNonNullValueKnownToDominateAllUsers(instruction, outValue);
      return true;
    }

    DynamicTypeWithUpperBound dynamicTypeWithUpperBound = dynamicType.asDynamicTypeWithUpperBound();
    DynamicTypeWithUpperBound staticType = DynamicType.create(appView, outValue.getType());
    if (!dynamicTypeWithUpperBound.strictlyLessThan(staticType, appView)) {
      return false;
    }

    if (!dynamicTypeWithUpperBound.getNullability().isMaybeNull()
        && dynamicTypeWithUpperBound.withNullability(Nullability.maybeNull()).equals(staticType)) {
      assert dynamicTypeWithUpperBound.getNullability().isDefinitelyNotNull();
      assumedValuesBuilder.addNonNullValueKnownToDominateAllUsers(instruction, outValue);
    } else {
      assumedValuesBuilder.addAssumedValueKnownToDominateAllUsers(
          instruction, outValue, dynamicTypeWithUpperBound);
    }
    return true;
  }

  private void removeRedundantAssumeInstructions(AssumedValues assumedValues) {
    assumedValues.removeIf(
        (instruction, assumedValue, assumedValueInfo) -> {
          // Assumed values with dynamic type information are never redundant.
          if (assumedValueInfo.hasDynamicTypeInfo()) {
            return false;
          }

          assert assumedValueInfo.isNonNull();

          // Otherwise, it is redundant if it is defined by another instruction that guarantees its
          // non-nullness.
          if (assumedValue.isPhi()) {
            return false;
          }

          Instruction definition = assumedValue.definition;
          if (definition == instruction) {
            return false;
          }

          AssumedValueInfo otherAssumedValueInfo =
              assumedValues.getAssumedValueInfo(definition, assumedValue);
          if (otherAssumedValueInfo == null) {
            return false;
          }

          if (!otherAssumedValueInfo.isNonNull()) {
            // This is not redundant, but we can strenghten it with the dynamic type information
            // from the other assume instruction.
            assumedValueInfo.setDynamicTypeAssumption(
                otherAssumedValueInfo.getDynamicTypeAssumption());
            return false;
          }

          return true;
        });
  }

  private Map<Instruction, Map<Value, AssumedValueInfo>> computeDominanceForAssumedValues(
      IRCode code, AssumedValues assumedValues) {
    Map<Instruction, Map<Value, AssumedValueInfo>> redundantAssumedValues = new IdentityHashMap<>();
    LazyDominatorTree lazyDominatorTree = new LazyDominatorTree(code);
    Map<BasicBlock, Set<BasicBlock>> dominatedBlocksCache = new IdentityHashMap<>();
    assumedValues.computeDominance(
        (instruction, assumedValue, assumedValueInfo) -> {
          Map<Value, AssumedValueInfo> alreadyAssumedValues =
              redundantAssumedValues.get(instruction);
          if (alreadyAssumedValues != null) {
            AssumedValueInfo alreadyAssumedValueInfo = alreadyAssumedValues.get(assumedValue);
            if (alreadyAssumedValueInfo != null) {
              if (assumedValueInfo.isSubsumedBy(alreadyAssumedValueInfo)) {
                // Returning redundant() will cause the entry (instruction, assumedValue) to be
                // removed.
                return AssumedDominance.redundant();
              }

              // This assume value is dominated by the other assume value, so strengthen this one.
              assumedValueInfo.strengthenWith(alreadyAssumedValueInfo);
            }
          }

          // If this value is the out-value of some instruction it is known to dominate all users.
          if (assumedValue == instruction.outValue()) {
            return AssumedDominance.everything();
          }

          // If we learn that this value is known to be non-null in the same block as it is defined,
          // and it is not used between its definition and the instruction that performs the null
          // check, then the non-null-value is known to dominate all other users than the null check
          // itself.
          BasicBlock block = instruction.getBlock();
          if (assumedValue.getBlock() == block
              && block.exit().isGoto()
              && !instruction.getBlock().hasCatchHandlers()) {
            InstructionIterator iterator = instruction.getBlock().iterator();
            if (!assumedValue.isPhi()) {
              iterator.nextUntil(x -> x != assumedValue.definition);
              iterator.previous();
            }
            boolean isUsedBeforeInstruction = false;
            while (iterator.hasNext()) {
              Instruction current = iterator.next();
              if (current == instruction) {
                break;
              }
              if (current.inValues().contains(assumedValue)
                  || current.getDebugValues().contains(assumedValue)) {
                isUsedBeforeInstruction = true;
                break;
              }
            }
            if (!isUsedBeforeInstruction) {
              return AssumedDominance.everythingElse();
            }
          }

          // Otherwise, we need a dominator tree to determine which users are dominated.
          BasicBlock insertionBlock = getInsertionBlock(instruction);

          assert assumedValue.hasPhiUsers()
              || assumedValue.uniqueUsers().stream().anyMatch(user -> user != instruction)
              || assumedValue.isArgument();

          // Find all users of the original value that are dominated by either the current block
          // or the new split-off block. Since NPE can be explicitly caught, nullness should be
          // propagated through dominance.
          DominatorTree dominatorTree = lazyDominatorTree.get();
          Set<BasicBlock> dominatedBlocks =
              dominatedBlocksCache.computeIfAbsent(
                  insertionBlock, x -> dominatorTree.dominatedBlocks(x, Sets.newIdentityHashSet()));

          AssumedDominance.Builder dominance = AssumedDominance.builder(assumedValue);
          for (Instruction user : assumedValue.uniqueUsers()) {
            if (user != instruction && dominatedBlocks.contains(user.getBlock())) {
              if (user.getBlock() == insertionBlock && insertionBlock == block) {
                Instruction first = block.iterator().nextUntil(x -> x == instruction || x == user);
                assert first != null;
                if (first == user) {
                  continue;
                }
              }
              dominance.addDominatedUser(user);

              // Record that there is no need to insert an assume instruction for the non-null-value
              // after the given user in case the user is also a null check for the non-null-value.
              redundantAssumedValues
                  .computeIfAbsent(user, ignore -> new IdentityHashMap<>())
                  .put(assumedValue, assumedValueInfo);
            }
          }
          for (Phi user : assumedValue.uniquePhiUsers()) {
            IntList dominatedPredecessorIndices =
                findDominatedPredecessorIndexesInPhi(user, assumedValue, dominatedBlocks);
            if (!dominatedPredecessorIndices.isEmpty()) {
              dominance.addDominatedPhiUser(user, dominatedPredecessorIndices);
            }
          }
          return dominance.build();
        });
    return redundantAssumedValues;
  }

  private void removeRedundantDominatedAssumeInstructions(
      AssumedValues assumedValues,
      Map<Instruction, Map<Value, AssumedValueInfo>> redundantAssumedValues) {
    assumedValues.removeAll(redundantAssumedValues);
  }

  private void materializeAssumeInstructions(IRCode code, AssumedValues assumedValues) {
    Set<Value> affectedValues = Sets.newIdentityHashSet();
    Map<BasicBlock, Map<Instruction, List<Instruction>>> pendingInsertions =
        new IdentityHashMap<>();

    // We materialize the assume instructions in two steps. First, we materialize all the assume
    // instructions that do not dominate everything. These assume instructions can refine previous
    // assume instructions, so we materialize those first as they are "stronger".
    //
    // Example:
    //   1. Object value = getNullableValueWithDynamicType();
    //   2. Object nullableValueWithDynamicType = assume(value, ...)
    //   3. checkNotNull(value);
    //   4. Object nonNullValueWithDynamicType = assume(value, ...)
    //   5. return value;
    //
    // In this example, we first materialize the assume instruction in line 4, and replace the
    // dominated use of `value` in line 5 by the new assumed value `nonNullValueWithDynamicType`.
    // Afterwards, we materialize the assume instruction in line 2, and replace all remaining users
    // of `value` by `nullableValueWithDynamicType`.
    //
    // Result:
    //   1. Object value = getNullableValueWithDynamicType();
    //   2. Object nullableValueWithDynamicType = assume(value, ...)
    //   3. checkNotNull(nullableValueWithDynamicType);
    //   4. Object nonNullValueWithDynamicType = assume(value, ...)
    //   5. return nonNullValueWithDynamicType;
    materializeSelectedAssumeInstructions(
        code,
        assumedValues,
        affectedValues,
        pendingInsertions,
        assumedValueInfo -> !assumedValueInfo.dominance.isEverything());
    materializeSelectedAssumeInstructions(
        code,
        assumedValues,
        affectedValues,
        pendingInsertions,
        assumedValueInfo -> assumedValueInfo.dominance.isEverything());
    pendingInsertions.forEach(
        (block, pendingInsertionsPerInstruction) -> {
          InstructionListIterator instructionIterator = block.listIterator(code);
          while (instructionIterator.hasNext() && !pendingInsertionsPerInstruction.isEmpty()) {
            Instruction instruction = instructionIterator.next();
            List<Instruction> pendingAssumeInstructions =
                pendingInsertionsPerInstruction.remove(instruction);
            if (pendingAssumeInstructions != null) {
              pendingAssumeInstructions.forEach(instructionIterator::add);
            }
          }
        });
    if (!affectedValues.isEmpty()) {
      new TypeAnalysis(appView).narrowing(affectedValues);
    }
  }

  private void materializeSelectedAssumeInstructions(
      IRCode code,
      AssumedValues assumedValues,
      Set<Value> affectedValues,
      Map<BasicBlock, Map<Instruction, List<Instruction>>> pendingInsertions,
      Predicate<AssumedValueInfo> predicate) {
    assumedValues.removeIf(
        (instruction, assumedValue, assumedValueInfo) -> {
          if (!predicate.test(assumedValueInfo)) {
            return false;
          }

          BasicBlock block = instruction.getBlock();
          BasicBlock insertionBlock = getInsertionBlock(instruction);

          AssumedDominance dominance = assumedValueInfo.getDominance();
          Value newValue =
              assumedValueInfo.isNull()
                  ? code.createValue(TypeElement.getNull())
                  : code.createValue(
                      assumedValueInfo.isNonNull()
                          ? assumedValue.getType().asReferenceType().asMeetWithNotNull()
                          : assumedValue.getType(),
                      assumedValue.getLocalInfo());
          if (dominance.isEverything()) {
            assumedValue.replaceUsers(newValue);
          } else if (dominance.isEverythingElse()) {
            assumedValue.replaceSelectiveInstructionUsers(newValue, user -> user != instruction);
            assumedValue.replacePhiUsers(newValue);
          } else if (dominance.isSomething()) {
            SomethingAssumedDominance somethingDominance = dominance.asSomething();
            somethingDominance
                .getDominatedPhiUsers()
                .forEach(
                    (user, indices) -> {
                      IntListIterator iterator = indices.iterator();
                      while (iterator.hasNext()) {
                        Value operand = user.getOperand(iterator.nextInt());
                        if (operand != assumedValue) {
                          assert operand.isDefinedByInstructionSatisfying(Instruction::isAssume);
                          iterator.remove();
                        }
                      }
                    });
            assumedValue.replaceSelectiveUsers(
                newValue,
                somethingDominance.getDominatedUsers(),
                somethingDominance.getDominatedPhiUsers());
          }
          affectedValues.addAll(newValue.affectedValues());

          Instruction assumeInstruction;
          if (assumedValueInfo.isNull()) {
            assumeInstruction = new ConstNumber(newValue, 0);
          } else {
            assumeInstruction =
                new Assume(
                    assumedValueInfo.dynamicTypeAssumption,
                    assumedValueInfo.nonNullAssumption,
                    newValue,
                    assumedValue,
                    instruction,
                    appView);
          }
          assumeInstruction.setPosition(instruction.getPosition());
          if (insertionBlock != block) {
            insertionBlock.listIterator(code).add(assumeInstruction);
          } else {
            pendingInsertions
                .computeIfAbsent(block, ignore -> new IdentityHashMap<>())
                .computeIfAbsent(instruction, ignore -> new ArrayList<>())
                .add(assumeInstruction);
          }
          return true;
        });
  }

  private BasicBlock getInsertionBlock(Instruction instruction) {
    if (instruction.isIf()) {
      return instruction.asIf().targetFromNonNullObject();
    }
    BasicBlock block = instruction.getBlock();
    if (block.hasCatchHandlers()) {
      return block.exit().asGoto().getTarget();
    }
    return block;
  }

  private IntList findDominatedPredecessorIndexesInPhi(
      Phi user, Value assumedValue, Set<BasicBlock> dominatedBlocks) {
    assert user.getOperands().contains(assumedValue);
    List<Value> operands = user.getOperands();
    List<BasicBlock> predecessors = user.getBlock().getPredecessors();
    assert operands.size() == predecessors.size();

    IntList predecessorIndexes = new IntArrayList();
    int index = 0;
    Iterator<Value> operandIterator = operands.iterator();
    Iterator<BasicBlock> predecessorIterator = predecessors.iterator();
    while (operandIterator.hasNext() && predecessorIterator.hasNext()) {
      Value operand = operandIterator.next();
      BasicBlock predecessor = predecessorIterator.next();
      // When this phi is chosen to be known-to-be-non-null value,
      // check if the corresponding predecessor is dominated by the block where non-null is added.
      if (operand == assumedValue && dominatedBlocks.contains(predecessor)) {
        predecessorIndexes.add(index);
      }

      index++;
    }
    return predecessorIndexes;
  }

  private static boolean isNullableReferenceType(Value value) {
    TypeElement type = value.getType();
    return type.isReferenceType() && type.asReferenceType().isNullable();
  }

  private static boolean isNullableReferenceTypeWithOtherNonDebugUsers(
      Value value, Instruction ignore) {
    if (isNullableReferenceType(value)) {
      if (value.hasPhiUsers()) {
        return true;
      }
      for (Instruction user : value.uniqueUsers()) {
        if (user != ignore) {
          return true;
        }
      }
    }
    return false;
  }

  static class AssumedValueInfo {

    AssumedDominance dominance;
    DynamicTypeAssumption dynamicTypeAssumption;
    NonNullAssumption nonNullAssumption;

    AssumedValueInfo(AssumedDominance dominance) {
      this.dominance = dominance;
    }

    AssumedDominance getDominance() {
      return dominance;
    }

    void setDominance(AssumedDominance dominance) {
      this.dominance = dominance;
    }

    boolean hasDynamicTypeInfo() {
      return dynamicTypeAssumption != null;
    }

    DynamicTypeAssumption getDynamicTypeAssumption() {
      return dynamicTypeAssumption;
    }

    void setDynamicTypeAssumption(DynamicTypeAssumption dynamicTypeAssumption) {
      this.dynamicTypeAssumption = dynamicTypeAssumption;
    }

    void setDynamicTypeAssumption(DynamicTypeWithUpperBound dynamicType) {
      assert dynamicType != null;
      dynamicTypeAssumption = new DynamicTypeAssumption(dynamicType);
      if (dynamicType.getDynamicUpperBoundType().isDefinitelyNotNull()) {
        setNotNull();
      }
    }

    boolean isNull() {
      return dynamicTypeAssumption != null
          && dynamicTypeAssumption.getDynamicType().getNullability().isDefinitelyNull();
    }

    boolean isNonNull() {
      return nonNullAssumption != null;
    }

    void setNotNull() {
      nonNullAssumption = NonNullAssumption.get();
    }

    boolean isSubsumedBy(AssumedValueInfo other) {
      return !hasDynamicTypeInfo() && other.isNonNull();
    }

    void strengthenWith(AssumedValueInfo info) {
      if (info.isNonNull()) {
        setNotNull();
      }
      if (!hasDynamicTypeInfo() && info.hasDynamicTypeInfo()) {
        setDynamicTypeAssumption(info.getDynamicTypeAssumption());
      }
    }
  }

  static class AssumedValues {

    /**
     * A mapping from each instruction to the (in and out) values that are guaranteed to be non-null
     * by the instruction. Each non-null value is subsequently mapped to the set of users that it
     * dominates.
     */
    Map<Instruction, Map<Value, AssumedValueInfo>> assumedValues;

    public AssumedValues(Map<Instruction, Map<Value, AssumedValueInfo>> assumedValues) {
      this.assumedValues = assumedValues;
    }

    public static Builder builder() {
      return new Builder();
    }

    void computeDominance(
        TriFunction<Instruction, Value, AssumedValueInfo, AssumedDominance> function) {
      Iterator<Entry<Instruction, Map<Value, AssumedValueInfo>>> outerIterator =
          assumedValues.entrySet().iterator();
      while (outerIterator.hasNext()) {
        Entry<Instruction, Map<Value, AssumedValueInfo>> outerEntry = outerIterator.next();
        Instruction instruction = outerEntry.getKey();
        Map<Value, AssumedValueInfo> dominancePerValue = outerEntry.getValue();
        Iterator<Entry<Value, AssumedValueInfo>> innerIterator =
            dominancePerValue.entrySet().iterator();
        while (innerIterator.hasNext()) {
          Entry<Value, AssumedValueInfo> innerEntry = innerIterator.next();
          Value assumedValue = innerEntry.getKey();
          AssumedValueInfo assumedValueInfo = innerEntry.getValue();
          AssumedDominance dominance = assumedValueInfo.dominance;
          if (dominance.isEverything()) {
            assert assumedValue.isDefinedByInstructionSatisfying(
                definition -> definition.outValue() == assumedValue);
            continue;
          }
          assert dominance.isUnknown();
          dominance = function.apply(instruction, assumedValue, assumedValueInfo);
          if ((dominance.isNothing() && !assumedValue.isArgument()) || dominance.isUnknown()) {
            innerIterator.remove();
          } else {
            assumedValueInfo.setDominance(dominance);
          }
        }
        if (dominancePerValue.isEmpty()) {
          outerIterator.remove();
        }
      }
    }

    AssumedValueInfo getAssumedValueInfo(Instruction instruction, Value assumedValue) {
      Map<Value, AssumedValueInfo> dominancePerValue = assumedValues.get(instruction);
      return dominancePerValue != null ? dominancePerValue.get(assumedValue) : null;
    }

    boolean isEmpty() {
      return assumedValues.isEmpty();
    }

    void forEach(TriConsumer<Instruction, Value, AssumedValueInfo> consumer) {
      assumedValues.forEach(
          (instruction, dominancePerValue) ->
              dominancePerValue.forEach(
                  (assumedValue, assumedValueInfo) ->
                      consumer.accept(instruction, assumedValue, assumedValueInfo)));
    }

    void removeAll(Map<Instruction, Map<Value, AssumedValueInfo>> keys) {
      keys.forEach(
          (instruction, redundantAssumedValues) -> {
            Map<Value, AssumedValueInfo> dominancePerValue = assumedValues.get(instruction);
            if (dominancePerValue != null) {
              redundantAssumedValues.keySet().forEach(dominancePerValue::remove);
              if (dominancePerValue.isEmpty()) {
                assumedValues.remove(instruction);
              }
            }
          });
    }

    void removeIf(TriPredicate<Instruction, Value, AssumedValueInfo> predicate) {
      Iterator<Entry<Instruction, Map<Value, AssumedValueInfo>>> outerIterator =
          assumedValues.entrySet().iterator();
      while (outerIterator.hasNext()) {
        Entry<Instruction, Map<Value, AssumedValueInfo>> outerEntry = outerIterator.next();
        Instruction instruction = outerEntry.getKey();
        Map<Value, AssumedValueInfo> dominancePerValue = outerEntry.getValue();
        Iterator<Entry<Value, AssumedValueInfo>> innerIterator =
            dominancePerValue.entrySet().iterator();
        while (innerIterator.hasNext()) {
          Entry<Value, AssumedValueInfo> innerEntry = innerIterator.next();
          Value assumedValue = innerEntry.getKey();
          AssumedValueInfo assumedValueInfo = innerEntry.getValue();
          if (predicate.test(instruction, assumedValue, assumedValueInfo)) {
            innerIterator.remove();
          }
        }
        if (dominancePerValue.isEmpty()) {
          outerIterator.remove();
        }
      }
    }

    static class Builder {

      private final Map<Instruction, Map<Value, AssumedValueInfo>> assumedValues =
          new LinkedHashMap<>();

      // Used to avoid unnecessary block splitting during phase 1.
      private final Set<Value> nonNullValuesKnownToDominateAllUsers = Sets.newIdentityHashSet();

      private void updateAssumedValueInfo(
          Instruction instruction,
          Value assumedValue,
          AssumedDominance dominance,
          Consumer<AssumedValueInfo> consumer) {
        AssumedValueInfo assumedValueInfo =
            assumedValues
                .computeIfAbsent(instruction, ignore -> new LinkedHashMap<>())
                .computeIfAbsent(assumedValue, ignore -> new AssumedValueInfo(dominance));
        consumer.accept(assumedValueInfo);
        if (dominance.isEverything() && assumedValueInfo.isNonNull()) {
          nonNullValuesKnownToDominateAllUsers.add(assumedValue);
        }
      }

      void addAssumedValueKnownToDominateAllUsers(
          Instruction instruction, Value assumedValue, DynamicTypeWithUpperBound dynamicType) {
        updateAssumedValueInfo(
            instruction,
            assumedValue,
            AssumedDominance.everything(),
            assumedValueInfo -> assumedValueInfo.setDynamicTypeAssumption(dynamicType));
      }

      void addNonNullValueKnownToDominateAllUsers(Instruction instruction, Value nonNullValue) {
        updateAssumedValueInfo(
            instruction, nonNullValue, AssumedDominance.everything(), AssumedValueInfo::setNotNull);
      }

      void addNonNullValueWithUnknownDominance(Instruction instruction, Value nonNullValue) {
        updateAssumedValueInfo(
            instruction, nonNullValue, AssumedDominance.unknown(), AssumedValueInfo::setNotNull);
      }

      public boolean isMaybeNull(Value value) {
        return !nonNullValuesKnownToDominateAllUsers.contains(value);
      }

      public AssumedValues build() {
        return new AssumedValues(assumedValues);
      }
    }
  }

  abstract static class AssumedDominance {

    boolean isEverything() {
      return false;
    }

    boolean isEverythingElse() {
      return false;
    }

    boolean isNothing() {
      return false;
    }

    boolean isSomething() {
      return false;
    }

    SomethingAssumedDominance asSomething() {
      return null;
    }

    boolean isUnknown() {
      return false;
    }

    public static Builder builder(Value assumedValue) {
      return new Builder(assumedValue);
    }

    public static EverythingAssumedDominance everything() {
      return EverythingAssumedDominance.getInstance();
    }

    public static EverythingElseAssumedDominance everythingElse() {
      return EverythingElseAssumedDominance.getInstance();
    }

    public static NothingAssumedDominance nothing() {
      return NothingAssumedDominance.getInstance();
    }

    public static UnknownAssumedDominance redundant() {
      return unknown();
    }

    public static SomethingAssumedDominance something(
        Set<Instruction> dominatedUsers, Map<Phi, IntList> dominatedPhiUsers) {
      return new SomethingAssumedDominance(dominatedUsers, dominatedPhiUsers);
    }

    public static UnknownAssumedDominance unknown() {
      return UnknownAssumedDominance.getInstance();
    }

    static class Builder {

      private final Value assumedValue;

      private final Set<Instruction> dominatedUsers = Sets.newIdentityHashSet();
      private final Map<Phi, IntList> dominatedPhiUsers = new IdentityHashMap<>();

      private Builder(Value assumedValue) {
        this.assumedValue = assumedValue;
      }

      void addDominatedUser(Instruction user) {
        assert assumedValue.uniqueUsers().contains(user);
        assert !dominatedUsers.contains(user);
        dominatedUsers.add(user);
      }

      void addDominatedPhiUser(Phi user, IntList dominatedPredecessorIndices) {
        assert assumedValue.uniquePhiUsers().contains(user);
        assert !dominatedPhiUsers.containsKey(user);
        dominatedPhiUsers.put(user, dominatedPredecessorIndices);
      }

      AssumedDominance build() {
        if (dominatedUsers.isEmpty() && dominatedPhiUsers.isEmpty()) {
          return nothing();
        }
        assert dominatedUsers.size() < assumedValue.uniqueUsers().size()
            || dominatedPhiUsers.size() < assumedValue.uniquePhiUsers().size();
        return something(dominatedUsers, dominatedPhiUsers);
      }
    }
  }

  static class EverythingAssumedDominance extends AssumedDominance {

    private static final EverythingAssumedDominance INSTANCE = new EverythingAssumedDominance();

    private EverythingAssumedDominance() {}

    public static EverythingAssumedDominance getInstance() {
      return INSTANCE;
    }

    @Override
    boolean isEverything() {
      return true;
    }
  }

  static class EverythingElseAssumedDominance extends AssumedDominance {

    private static final EverythingElseAssumedDominance INSTANCE =
        new EverythingElseAssumedDominance();

    private EverythingElseAssumedDominance() {}

    public static EverythingElseAssumedDominance getInstance() {
      return INSTANCE;
    }

    @Override
    boolean isEverythingElse() {
      return true;
    }
  }

  static class NothingAssumedDominance extends AssumedDominance {

    private static final NothingAssumedDominance INSTANCE = new NothingAssumedDominance();

    private NothingAssumedDominance() {}

    public static NothingAssumedDominance getInstance() {
      return INSTANCE;
    }

    @Override
    boolean isNothing() {
      return true;
    }
  }

  static class SomethingAssumedDominance extends AssumedDominance {

    private final Set<Instruction> dominatedUsers;
    private final Map<Phi, IntList> dominatedPhiUsers;

    SomethingAssumedDominance(
        Set<Instruction> dominatedUsers, Map<Phi, IntList> dominatedPhiUsers) {
      this.dominatedUsers = dominatedUsers;
      this.dominatedPhiUsers = dominatedPhiUsers;
    }

    public Set<Instruction> getDominatedUsers() {
      return dominatedUsers;
    }

    public Map<Phi, IntList> getDominatedPhiUsers() {
      return dominatedPhiUsers;
    }

    @Override
    boolean isSomething() {
      return true;
    }

    @Override
    SomethingAssumedDominance asSomething() {
      return this;
    }
  }

  static class UnknownAssumedDominance extends AssumedDominance {

    private static final UnknownAssumedDominance INSTANCE = new UnknownAssumedDominance();

    private UnknownAssumedDominance() {}

    public static UnknownAssumedDominance getInstance() {
      return INSTANCE;
    }

    @Override
    boolean isUnknown() {
      return true;
    }
  }
}
