// Copyright (c) 2017, 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.code.Opcodes.CONST_CLASS;
import static com.android.tools.r8.ir.code.Opcodes.CONST_NUMBER;
import static com.android.tools.r8.ir.code.Opcodes.CONST_STRING;
import static com.android.tools.r8.ir.code.Opcodes.DEX_ITEM_BASED_CONST_STRING;
import static com.android.tools.r8.ir.code.Opcodes.INSTANCE_GET;
import static com.android.tools.r8.ir.code.Opcodes.STATIC_GET;
import static com.android.tools.r8.utils.MapUtils.ignoreKey;

import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.FieldAccessFlags;
import com.android.tools.r8.graph.FieldResolutionResult.SingleFieldResolutionResult;
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.SingleFieldValue;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.BasicBlockIterator;
import com.android.tools.r8.ir.code.ConstClass;
import com.android.tools.r8.ir.code.ConstNumber;
import com.android.tools.r8.ir.code.ConstString;
import com.android.tools.r8.ir.code.DexItemBasedConstString;
import com.android.tools.r8.ir.code.FieldGet;
import com.android.tools.r8.ir.code.FieldInstruction;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.InstanceGet;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.InstructionOrPhi;
import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.code.NewInstance;
import com.android.tools.r8.ir.code.Phi;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.StaticGet;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.utils.OptionalBool;
import com.android.tools.r8.utils.WorkList;
import com.google.common.collect.Sets;
import it.unimi.dsi.fastutil.Hash.Strategy;
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenCustomHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectSortedMap.FastSortedEntrySet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Canonicalize constants.
 */
public class ConstantCanonicalizer {

  // Threshold to limit the number of constant canonicalization.
  private static final int MAX_CANONICALIZED_CONSTANT = 22;

  private final AppView<?> appView;
  private final CodeRewriter codeRewriter;
  private final ProgramMethod context;
  private final IRCode code;

  private OptionalBool isAccessingVolatileField = OptionalBool.unknown();
  private Set<InstanceGet> ineligibleInstanceGetInstructions;

  public ConstantCanonicalizer(
      AppView<?> appView, CodeRewriter codeRewriter, ProgramMethod context, IRCode code) {
    this.appView = appView;
    this.codeRewriter = codeRewriter;
    this.context = context;
    this.code = code;
  }

  private ConstantCanonicalizer clear() {
    isAccessingVolatileField = OptionalBool.unknown();
    ineligibleInstanceGetInstructions = null;
    return this;
  }

  private boolean getOrComputeIsAccessingVolatileField() {
    if (isAccessingVolatileField.isUnknown()) {
      isAccessingVolatileField = OptionalBool.of(computeIsAccessingVolatileField());
    }
    return isAccessingVolatileField.isTrue();
  }

  private boolean computeIsAccessingVolatileField() {
    if (!appView.hasClassHierarchy()) {
      // Conservatively return true.
      return true;
    }
    AppInfoWithClassHierarchy appInfo = appView.appInfoWithClassHierarchy();
    for (FieldInstruction fieldGet :
        code.<FieldInstruction>instructions(Instruction::isFieldInstruction)) {
      SingleFieldResolutionResult<?> resolutionResult =
          appInfo.resolveField(fieldGet.getField()).asSingleFieldResolutionResult();
      if (resolutionResult == null
          || resolutionResult.getResolvedField().getAccessFlags().isVolatile()) {
        return true;
      }
    }
    return false;
  }

  private Set<InstanceGet> getOrComputeIneligibleInstanceGetInstructions() {
    if (ineligibleInstanceGetInstructions == null) {
      ineligibleInstanceGetInstructions = computeIneligibleInstanceGetInstructions();
    }
    return ineligibleInstanceGetInstructions;
  }

  private Set<InstanceGet> computeIneligibleInstanceGetInstructions() {
    Set<InstanceGet> ineligibleInstanceGetInstructions = Sets.newIdentityHashSet();
    for (BasicBlock catchHandlerBlock : computeDirectAndIndirectCatchHandlerBlocks()) {
      for (InstanceGet instanceGet :
          catchHandlerBlock.<InstanceGet>getInstructions(Instruction::isInstanceGet)) {
        // If the receiver is defined in a block with catch handlers and the definition of the
        // receiver is not throwing (typically defined by an assume instruction or a phi), then we
        // cant split the block and copy the catch handlers, since the canonicalized constant would
        // then not be defined on the exceptional edge.
        Value object = instanceGet.object();
        if (!object.isDefinedByInstructionSatisfying(Instruction::instructionTypeCanThrow)
            && object.getBlock().hasCatchHandlers()) {
          ineligibleInstanceGetInstructions.add(instanceGet);
        }
      }
    }
    return ineligibleInstanceGetInstructions;
  }

  private Set<BasicBlock> computeDirectAndIndirectCatchHandlerBlocks() {
    WorkList<BasicBlock> catchHandlerBlocks = WorkList.newIdentityWorkList();
    for (BasicBlock block : code.getBlocks()) {
      if (block.entry().isMoveException()) {
        catchHandlerBlocks.addIfNotSeen(block);
      }
    }
    while (catchHandlerBlocks.hasNext()) {
      BasicBlock block = catchHandlerBlocks.next();
      catchHandlerBlocks.addIfNotSeen(block.getSuccessors());
    }
    return catchHandlerBlocks.getSeenSet();
  }

  public ConstantCanonicalizer canonicalize() {
    Object2ObjectLinkedOpenCustomHashMap<Instruction, List<Instruction>> valuesDefinedByConstant =
        new Object2ObjectLinkedOpenCustomHashMap<>(
            new Strategy<Instruction>() {

              @Override
              public int hashCode(Instruction candidate) {
                assert candidate.instructionTypeCanBeCanonicalized();
                switch (candidate.opcode()) {
                  case CONST_CLASS:
                    return candidate.asConstClass().getValue().hashCode();
                  case CONST_NUMBER:
                    return Long.hashCode(candidate.asConstNumber().getRawValue())
                        + 13 * candidate.outType().hashCode();
                  case CONST_STRING:
                    return candidate.asConstString().getValue().hashCode();
                  case DEX_ITEM_BASED_CONST_STRING:
                    return candidate.asDexItemBasedConstString().getItem().hashCode();
                  case INSTANCE_GET:
                  case STATIC_GET:
                    return candidate.asFieldGet().getField().hashCode();
                  default:
                    throw new Unreachable();
                }
              }

              @Override
              public boolean equals(Instruction a, Instruction b) {
                if (a == b) {
                  return true;
                }
                if (a == null || b == null || a.getClass() != b.getClass()) {
                  return false;
                }
                if (a.isInstanceGet() && a.getFirstOperand() != b.getFirstOperand()) {
                  return false;
                }
                return a.identicalNonValueNonPositionParts(b);
              }
            });

    // Collect usages of constants that can be canonicalized.
    for (Instruction instruction : code.instructions()) {
      if (isConstantCanonicalizationCandidate(instruction)) {
        valuesDefinedByConstant
            .computeIfAbsent(instruction, ignoreKey(ArrayList::new))
            .add(instruction);
      }
    }

    if (valuesDefinedByConstant.isEmpty()) {
      return clear();
    }

    // Double-check the entry block does not have catch handlers.
    // Otherwise, we need to split it before moving canonicalized const-string, which may throw.
    assert !code.entryBlock().hasCatchHandlers();
    FastSortedEntrySet<Instruction, List<Instruction>> entries =
        valuesDefinedByConstant.object2ObjectEntrySet();
    // Sort the most frequently used constant first and exclude constant use only one time, such
    // as the {@code MAX_CANONICALIZED_CONSTANT} will be canonicalized into the entry block.
    Iterator<Object2ObjectMap.Entry<Instruction, List<Instruction>>> iterator =
        entries.stream()
            .filter(a -> a.getValue().size() > 1)
            .sorted((a, b) -> Integer.compare(b.getValue().size(), a.getValue().size()))
            .limit(MAX_CANONICALIZED_CONSTANT)
            .iterator();
    if (!iterator.hasNext()) {
      return clear();
    }

    boolean shouldSimplifyIfs = false;

    // Insert instructions in the entry block.
    Map<InstructionOrPhi, List<Instruction>> pendingInsertions = new IdentityHashMap<>();
    do {
      Object2ObjectMap.Entry<Instruction, List<Instruction>> entry = iterator.next();
      Instruction canonicalizedConstant = entry.getKey();
      assert canonicalizedConstant.instructionTypeCanBeCanonicalized();
      Instruction newInstruction;
      if (canonicalizedConstant.getBlock().isEntry()) {
        newInstruction = canonicalizedConstant;
      } else {
        newInstruction = createMaterializingInstruction(canonicalizedConstant);
        InstructionOrPhi insertionPoint = getInsertionPointForCanonicalizedConstant(newInstruction);
        if (insertionPoint == null) {
          insertCanonicalizedConstantInEntryBlock(newInstruction);
        } else {
          // Record that this instruction needs to be inserted at the insertion position. Note that
          // the insertion position may later be moved if it is itself subject to canonicalization.
          addPendingInsertion(insertionPoint, newInstruction, pendingInsertions);
        }
      }
      // Remove the canonicalized instructions.
      for (Instruction oldInstruction : entry.getValue()) {
        if (oldInstruction != newInstruction) {
          oldInstruction.outValue().replaceUsers(newInstruction.outValue());
          oldInstruction
              .getBlock()
              .listIterator(code, oldInstruction)
              .removeOrReplaceByDebugLocalRead();

          // If the removed instruction is an insertion point for another constant, then record that
          // the constant should instead be inserted at the point where the removed instruction has
          // been moved to.
          for (Instruction pendingInsertion :
              removePendingInsertions(oldInstruction, pendingInsertions)) {
            addPendingInsertion(newInstruction, pendingInsertion, pendingInsertions);
          }
        }
      }
      shouldSimplifyIfs |= newInstruction.outValue().hasUserThatMatches(Instruction::isIf);
    } while (iterator.hasNext());

    // Insert instructions that cannot be inserted in the entry block.
    if (!pendingInsertions.isEmpty()) {
      BasicBlockIterator blockIterator = code.listIterator();
      while (blockIterator.hasNext()) {
        BasicBlock block = blockIterator.next();
        InstructionListIterator instructionIterator = block.listIterator(code);
        for (Phi insertionPoint : block.getPhis()) {
          instructionIterator =
              insertPendingInsertions(
                  blockIterator, instructionIterator, insertionPoint, pendingInsertions);
        }
        while (instructionIterator.hasNext()) {
          Instruction insertionPoint = instructionIterator.next();
          instructionIterator =
              insertPendingInsertions(
                  blockIterator, instructionIterator, insertionPoint, pendingInsertions);
        }
      }
    }

    assert pendingInsertions.isEmpty();

    shouldSimplifyIfs |= code.removeAllDeadAndTrivialPhis();

    if (shouldSimplifyIfs) {
      codeRewriter.simplifyIf(code);
    }

    assert code.isConsistentSSA(appView);
    return clear();
  }

  private void addPendingInsertion(
      InstructionOrPhi insertionPoint,
      Instruction newInstruction,
      Map<InstructionOrPhi, List<Instruction>> pendingInsertions) {
    pendingInsertions
        .computeIfAbsent(insertionPoint, ignoreKey(ArrayList::new))
        .add(newInstruction);
  }

  private InstructionListIterator insertPendingInsertions(
      BasicBlockIterator blockIterator,
      InstructionListIterator instructionIterator,
      InstructionOrPhi insertionPoint,
      Map<InstructionOrPhi, List<Instruction>> pendingInsertions) {
    List<Instruction> pendingInsertionsAtInsertionPoint =
        removePendingInsertions(insertionPoint, pendingInsertions);
    if (pendingInsertionsAtInsertionPoint.isEmpty()) {
      return instructionIterator;
    }
    WorkList<Instruction> worklist =
        WorkList.newIdentityWorkList(pendingInsertionsAtInsertionPoint);
    while (worklist.hasNext()) {
      Instruction newInstruction = worklist.next();
      List<Instruction> pendingInsertionsAfterNewInstruction =
          removePendingInsertions(newInstruction, pendingInsertions);
      if (pendingInsertionsAfterNewInstruction.isEmpty()) {
        instructionIterator =
            insertCanonicalizedConstantAtInsertionPoint(
                blockIterator, instructionIterator, insertionPoint, newInstruction);
      } else {
        // Process pending insertions before the current instruction to ensure the current
        // instruction ends up first in the instruction stream.
        worklist.addIfNotSeen(pendingInsertionsAfterNewInstruction);
        worklist.addIgnoringSeenSet(newInstruction);
      }
    }
    return instructionIterator;
  }

  private List<Instruction> removePendingInsertions(
      InstructionOrPhi insertionPoint, Map<InstructionOrPhi, List<Instruction>> pendingInsertions) {
    List<Instruction> pendingInstructionsAtInsertionPosition =
        pendingInsertions.remove(insertionPoint);
    return pendingInstructionsAtInsertionPosition != null
        ? pendingInstructionsAtInsertionPosition
        : Collections.emptyList();
  }

  private InstructionOrPhi getInsertionPointForCanonicalizedConstant(Instruction newInstruction) {
    switch (newInstruction.opcode()) {
      case CONST_CLASS:
      case CONST_NUMBER:
      case CONST_STRING:
      case DEX_ITEM_BASED_CONST_STRING:
      case STATIC_GET:
        // Insert in entry block.
        return null;
      case INSTANCE_GET:
        {
          InstanceGet instanceGet = newInstruction.asInstanceGet();
          Value object = instanceGet.object();
          if (object.isThis()) {
            return null;
          }
          if (object.isPhi()) {
            return object.asPhi();
          }
          Instruction definition = object.getDefinition();
          if (definition.isArgument()) {
            return code.getLastArgument();
          }
          if (definition.isNewInstance()) {
            InvokeDirect uniqueConstructorInvoke =
                definition.asNewInstance().getUniqueConstructorInvoke(appView.dexItemFactory());
            // This is guaranteed to be non-null by isConstantCanonicalizationCandidate.
            assert uniqueConstructorInvoke != null;
            return uniqueConstructorInvoke;
          }
          return definition;
        }
      default:
        throw new Unreachable();
    }
  }

  private Instruction createMaterializingInstruction(Instruction canonicalizedConstant) {
    switch (canonicalizedConstant.opcode()) {
      case CONST_CLASS:
        return ConstClass.copyOf(code, canonicalizedConstant.asConstClass());
      case CONST_NUMBER:
        return ConstNumber.copyOf(code, canonicalizedConstant.asConstNumber());
      case CONST_STRING:
        return ConstString.copyOf(code, canonicalizedConstant.asConstString());
      case DEX_ITEM_BASED_CONST_STRING:
        return DexItemBasedConstString.copyOf(
            code, canonicalizedConstant.asDexItemBasedConstString());
      case INSTANCE_GET:
        return InstanceGet.copyOf(code, canonicalizedConstant.asInstanceGet());
      case STATIC_GET:
        return StaticGet.copyOf(code, canonicalizedConstant.asStaticGet());
      default:
        throw new Unreachable();
    }
  }

  public boolean isConstantCanonicalizationCandidate(Instruction instruction) {
    // Interested only in instructions types that can be canonicalized, i.e., ConstClass,
    // ConstNumber, (DexItemBased)?ConstString, InstanceGet and StaticGet.
    switch (instruction.opcode()) {
      case CONST_CLASS:
        // Do not canonicalize ConstClass that may have side effects. Its original instructions
        // will not be removed by dead code remover due to the side effects.
        if (instruction.instructionMayHaveSideEffects(appView, context)) {
          return false;
        }
        break;
      case CONST_NUMBER:
        break;
      case CONST_STRING:
      case DEX_ITEM_BASED_CONST_STRING:
        break;
      case INSTANCE_GET:
        {
          InstanceGet instanceGet = instruction.asInstanceGet();
          if (instanceGet.instructionMayHaveSideEffects(appView, context)) {
            return false;
          }
          if (instanceGet.object().isDefinedByInstructionSatisfying(Instruction::isNewInstance)) {
            NewInstance newInstance = instanceGet.object().getDefinition().asNewInstance();
            if (newInstance.getUniqueConstructorInvoke(appView.dexItemFactory()) == null) {
              return false;
            }
          }
          if (!isReadOfFinalFieldOutsideInitializer(instanceGet)) {
            return false;
          }
          if (getOrComputeIneligibleInstanceGetInstructions().contains(instanceGet)) {
            return false;
          }
          break;
        }
      case STATIC_GET:
        {
          // Canonicalize effectively final fields that are guaranteed to be written before they are
          // read. This is only OK if the instruction cannot have side effects.
          StaticGet staticGet = instruction.asStaticGet();
          if (staticGet.instructionMayHaveSideEffects(appView, context)) {
            return false;
          }
          if (!isReadOfFinalFieldOutsideInitializer(staticGet)
              && !isEffectivelyFinalField(staticGet)) {
            return false;
          }
          break;
        }
      default:
        assert !instruction.instructionTypeCanBeCanonicalized() : instruction.toString();
        return false;
    }
    // Constants with local info must not be canonicalized and must be filtered.
    if (instruction.outValue().hasLocalInfo()) {
      return false;
    }
    // Do not canonicalize throwing instructions if there are monitor operations in the code.
    // That could lead to unbalanced locking and could lead to situations where OOM exceptions
    // could leave a synchronized method without unlocking the monitor.
    if (instruction.instructionTypeCanThrow() && code.metadata().mayHaveMonitorInstruction()) {
      return false;
    }
    // Constants that are used by invoke range are not canonicalized to be compliant with the
    // optimization splitRangeInvokeConstant that gives the register allocator more freedom in
    // assigning register to ranged invokes which can greatly reduce the number of register
    // needed (and thereby code size as well). Thus no need to do a transformation that should
    // be removed later by another optimization.
    if (constantUsedByInvokeRange(instruction)) {
      return false;
    }
    return true;
  }

  private boolean isReadOfFinalFieldOutsideInitializer(FieldGet fieldGet) {
    if (getOrComputeIsAccessingVolatileField()) {
      // A final field may be initialized concurrently. A requirement for this is that the field is
      // volatile. However, the reading or writing of another volatile field also allows for
      // concurrently initializing a non-volatile field. See also redundant field load elimination.
      return false;
    }
    AppView<? extends AppInfoWithClassHierarchy> appViewWithClassHierarchy =
        appView.withClassHierarchy();
    SingleFieldResolutionResult<?> resolutionResult =
        appViewWithClassHierarchy
            .appInfo()
            .resolveField(fieldGet.getField())
            .asSingleFieldResolutionResult();
    if (resolutionResult == null) {
      // Not known to be final.
      return false;
    }
    if (!resolutionResult.isSingleProgramFieldResolutionResult()) {
      // We can't rely on the final flag of non-program fields.
      return false;
    }
    ProgramField resolvedField = resolutionResult.getSingleProgramField();
    FieldAccessFlags accessFlags = resolvedField.getAccessFlags();
    assert !accessFlags.isVolatile();
    // TODO(b/236661949): Add support for effectively final fields so that this also works well
    //  without -allowaccessmodification.
    if (!accessFlags.isFinal()) {
      return false;
    }
    if (appView.getKeepInfo(resolvedField).isPinned(appView.options())) {
      // The final flag could be unset using reflection.
      return false;
    }
    if (context.getDefinition().isInitializer()
        && context.getAccessFlags().isStatic() == fieldGet.isStaticGet()) {
      if (context.getHolder() == resolvedField.getHolder()) {
        // If this is an initializer on the field's holder, then bail out, since the field value is
        // only known to be final after object/class creation.
        return false;
      }
      if (fieldGet.isInstanceGet()
          && appViewWithClassHierarchy
              .appInfo()
              .isSubtype(context.getHolder(), resolvedField.getHolder())) {
        // If an instance initializer reads a final instance field declared in a super class, we
        // cannot hoist the read above the parent constructor call.
        return false;
      }
    }
    if (!resolutionResult.getInitialResolutionHolder().isResolvable(appView)) {
      // If this field read is guarded by an API level check, hoisting of this field could lead to
      // a ClassNotFoundException on some API levels.
      return false;
    }
    return true;
  }

  private boolean isEffectivelyFinalField(StaticGet staticGet) {
    AbstractValue abstractValue = staticGet.outValue().getAbstractValue(appView, context);
    if (!abstractValue.isSingleFieldValue()) {
      return false;
    }
    SingleFieldValue singleFieldValue = abstractValue.asSingleFieldValue();
    DexType fieldHolderType = singleFieldValue.getField().getHolderType();
    if (context.getDefinition().isClassInitializer()
        && context.getHolderType() == fieldHolderType) {
      // Avoid that canonicalization inserts a read before the unique write in the class
      // initializer, as that would change the program behavior.
      return false;
    }
    DexClass fieldHolder = appView.definitionFor(fieldHolderType);
    return singleFieldValue.getField().lookupOnClass(fieldHolder) != null;
  }

  private void insertCanonicalizedConstantInEntryBlock(Instruction canonicalizedConstant) {
    BasicBlock entryBlock = code.entryBlock();
    // Insert the constant instruction at the start of the block right after the argument
    // instructions. It is important that the const instruction is put before any instruction
    // that can throw exceptions (since the value could be used on the exceptional edge).
    InstructionListIterator it = entryBlock.listIterator(code);
    while (it.hasNext()) {
      Instruction next = it.next();
      if (!next.isArgument()) {
        canonicalizedConstant.setPosition(code.getEntryPosition());
        it.previous();
        break;
      }
    }
    it.add(canonicalizedConstant);
  }

  private InstructionListIterator insertCanonicalizedConstantAtInsertionPoint(
      BasicBlockIterator blockIterator,
      InstructionListIterator instructionIterator,
      InstructionOrPhi insertionPoint,
      Instruction newInstruction) {
    // If the insertion point is a phi, then we're inserting the new instruction before all other
    // instructions in the block.
    assert !insertionPoint.isPhi() || !instructionIterator.hasPrevious();
    // If the insertion point is not a phi, the iterator is positioned immediately after the
    // insertion point.
    assert insertionPoint.isPhi() || instructionIterator.peekPrevious() == insertionPoint;
    newInstruction.setPosition(
        getPositionForCanonicalizationConstantAtInsertionPoint(insertionPoint, newInstruction));
    if (newInstruction.instructionTypeCanThrow()
        && insertionPoint.getBlock().hasCatchHandlers()
        && insertionPoint.getBlock().canThrow()) {
      // Split the block and rewind the block iterator to the insertion block.
      BasicBlock splitBlock =
          instructionIterator.splitCopyCatchHandlers(code, blockIterator, appView.options());
      BasicBlock previousBlock =
          blockIterator.previousUntil(block -> block == insertionPoint.getBlock());
      assert previousBlock == insertionPoint.getBlock();
      blockIterator.next();
      if (insertionPoint.isPhi()) {
        // Add new instruction before the goto and position the instruction iterator before the
        // first instruction (i.e., at the phi position).
        assert insertionPoint.getBlock().getInstructions().size() == 1;
        instructionIterator.previous();
        instructionIterator.add(newInstruction);
        instructionIterator.previous();
        assert !instructionIterator.hasPrevious();
      } else {
        // Add the new instruction after the insertion point. If the block containing the insertion
        // point can throw, we insert the new instruction in the beginning of the split block.
        // Otherwise, we insert it in the end of the insertion block.
        if (insertionPoint.getBlock().canThrow()) {
          assert !splitBlock.canThrow();
          splitBlock.listIterator(code).add(newInstruction);
          instructionIterator.previous(2);
          Instruction next = instructionIterator.next();
          assert next == insertionPoint;
        } else {
          assert splitBlock.canThrow();
          instructionIterator.previous();
          instructionIterator.add(newInstruction);
          instructionIterator.previous(2);
          Instruction next = instructionIterator.next();
          assert next == insertionPoint;
        }
      }
    } else {
      instructionIterator.add(newInstruction);
      Instruction previous = instructionIterator.previous();
      assert previous == newInstruction;
    }
    return instructionIterator;
  }

  private Position getPositionForCanonicalizationConstantAtInsertionPoint(
      InstructionOrPhi insertionPoint, Instruction newInstruction) {
    Position insertionPosition =
        insertionPoint.isPhi()
            ? insertionPoint.getBlock().getPosition()
            : insertionPoint.asInstruction().getPosition();
    if (newInstruction.instructionTypeCanThrow() && insertionPosition.isNone()) {
      return Position.syntheticNone();
    }
    return insertionPosition;
  }

  private static boolean constantUsedByInvokeRange(Instruction constant) {
    for (Instruction user : constant.outValue().uniqueUsers()) {
      if (user.isInvoke() && user.asInvoke().requiredArgumentRegisters() > 5) {
        return true;
      }
    }
    return false;
  }
}
