// Copyright (c) 2021, 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.enums;

import static com.android.tools.r8.ir.analysis.type.Nullability.definitelyNotNull;
import static com.android.tools.r8.ir.code.Opcodes.ARRAY_GET;
import static com.android.tools.r8.ir.code.Opcodes.ARRAY_LENGTH;
import static com.android.tools.r8.ir.code.Opcodes.ARRAY_PUT;
import static com.android.tools.r8.ir.code.Opcodes.ASSUME;
import static com.android.tools.r8.ir.code.Opcodes.CHECK_CAST;
import static com.android.tools.r8.ir.code.Opcodes.CONST_CLASS;
import static com.android.tools.r8.ir.code.Opcodes.IF;
import static com.android.tools.r8.ir.code.Opcodes.INIT_CLASS;
import static com.android.tools.r8.ir.code.Opcodes.INSTANCE_GET;
import static com.android.tools.r8.ir.code.Opcodes.INSTANCE_PUT;
import static com.android.tools.r8.ir.code.Opcodes.INVOKE_CUSTOM;
import static com.android.tools.r8.ir.code.Opcodes.INVOKE_DIRECT;
import static com.android.tools.r8.ir.code.Opcodes.INVOKE_INTERFACE;
import static com.android.tools.r8.ir.code.Opcodes.INVOKE_STATIC;
import static com.android.tools.r8.ir.code.Opcodes.INVOKE_SUPER;
import static com.android.tools.r8.ir.code.Opcodes.INVOKE_VIRTUAL;
import static com.android.tools.r8.ir.code.Opcodes.RETURN;
import static com.android.tools.r8.ir.code.Opcodes.STATIC_GET;
import static com.android.tools.r8.ir.code.Opcodes.STATIC_PUT;
import static com.android.tools.r8.utils.MapUtils.ignoreKey;

import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClassAndField;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexMethodHandle;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.FieldResolutionResult;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
import com.android.tools.r8.ir.analysis.fieldvalueanalysis.StaticFieldValues;
import com.android.tools.r8.ir.analysis.fieldvalueanalysis.StaticFieldValues.EnumStaticFieldValues;
import com.android.tools.r8.ir.analysis.type.ArrayTypeElement;
import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.objectstate.EnumValuesObjectState;
import com.android.tools.r8.ir.analysis.value.objectstate.ObjectState;
import com.android.tools.r8.ir.code.ArrayGet;
import com.android.tools.r8.ir.code.ArrayLength;
import com.android.tools.r8.ir.code.ArrayPut;
import com.android.tools.r8.ir.code.Assume;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.CheckCast;
import com.android.tools.r8.ir.code.ConstClass;
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.InitClass;
import com.android.tools.r8.ir.code.InstanceGet;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InvokeCustom;
import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.code.InvokeStatic;
import com.android.tools.r8.ir.code.InvokeVirtual;
import com.android.tools.r8.ir.code.MemberType;
import com.android.tools.r8.ir.code.Phi;
import com.android.tools.r8.ir.code.Return;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.conversion.IRConverter;
import com.android.tools.r8.ir.conversion.MethodConversionOptions.MutableMethodConversionOptions;
import com.android.tools.r8.ir.conversion.MethodProcessor;
import com.android.tools.r8.ir.conversion.PostMethodProcessor.Builder;
import com.android.tools.r8.ir.desugar.LambdaDescriptor;
import com.android.tools.r8.ir.optimize.enums.EnumDataMap.EnumData;
import com.android.tools.r8.ir.optimize.enums.EnumInstanceFieldData.EnumInstanceFieldKnownData;
import com.android.tools.r8.ir.optimize.enums.EnumInstanceFieldData.EnumInstanceFieldMappingData;
import com.android.tools.r8.ir.optimize.enums.EnumInstanceFieldData.EnumInstanceFieldOrdinalData;
import com.android.tools.r8.ir.optimize.enums.EnumInstanceFieldData.EnumInstanceFieldUnknownData;
import com.android.tools.r8.ir.optimize.enums.classification.CheckNotNullEnumUnboxerMethodClassification;
import com.android.tools.r8.ir.optimize.enums.classification.EnumUnboxerMethodClassification;
import com.android.tools.r8.ir.optimize.enums.eligibility.Reason;
import com.android.tools.r8.ir.optimize.enums.eligibility.Reason.IllegalInvokeWithImpreciseParameterTypeReason;
import com.android.tools.r8.ir.optimize.enums.eligibility.Reason.MissingContentsForEnumValuesArrayReason;
import com.android.tools.r8.ir.optimize.enums.eligibility.Reason.MissingEnumStaticFieldValuesReason;
import com.android.tools.r8.ir.optimize.enums.eligibility.Reason.MissingInstanceFieldValueForEnumInstanceReason;
import com.android.tools.r8.ir.optimize.enums.eligibility.Reason.MissingObjectStateForEnumInstanceReason;
import com.android.tools.r8.ir.optimize.enums.eligibility.Reason.UnsupportedInstanceFieldValueForEnumInstanceReason;
import com.android.tools.r8.ir.optimize.enums.eligibility.Reason.UnsupportedLibraryInvokeReason;
import com.android.tools.r8.ir.optimize.info.MutableFieldOptimizationInfo;
import com.android.tools.r8.ir.optimize.info.MutableMethodOptimizationInfo;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedback.OptimizationInfoFixer;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackDelayed;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.KeepInfoCollection;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.collections.ImmutableInt2ReferenceSortedMap;
import com.android.tools.r8.utils.collections.LongLivedClassSetBuilder;
import com.android.tools.r8.utils.collections.LongLivedProgramMethodMapBuilder;
import com.android.tools.r8.utils.collections.LongLivedProgramMethodSetBuilder;
import com.android.tools.r8.utils.collections.ProgramMethodMap;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import it.unimi.dsi.fastutil.ints.Int2ReferenceArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.OptionalInt;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.function.Consumer;
import java.util.function.Function;

public class EnumUnboxerImpl extends EnumUnboxer {

  private final AppView<AppInfoWithLiveness> appView;
  private final DexItemFactory factory;
  // Map the enum candidates with their dependencies, i.e., the methods to reprocess for the given
  // enum if the optimization eventually decides to unbox it.
  private EnumUnboxingCandidateInfoCollection enumUnboxingCandidatesInfo;
  private final Set<DexProgramClass> candidatesToRemoveInWave = Sets.newConcurrentHashSet();
  private final Map<DexType, EnumStaticFieldValues> staticFieldValuesMap =
      new ConcurrentHashMap<>();

  // Methods depending on library modelisation need to be reprocessed so they are peephole
  // optimized.
  private LongLivedProgramMethodSetBuilder<ProgramMethodSet> methodsDependingOnLibraryModelisation;

  // Map from checkNotNull() methods to the enums that use the given method.
  private LongLivedProgramMethodMapBuilder<LongLivedClassSetBuilder<DexProgramClass>>
      checkNotNullMethodsBuilder;

  private final DexClassAndField ordinalField;

  private EnumUnboxingRewriter enumUnboxerRewriter;

  private final boolean debugLogEnabled;
  private final Map<DexType, List<Reason>> debugLogs;

  EnumUnboxerImpl(AppView<AppInfoWithLiveness> appView) {
    this.appView = appView;
    this.factory = appView.dexItemFactory();
    if (appView.options().testing.enableEnumUnboxingDebugLogs) {
      debugLogEnabled = true;
      debugLogs = new ConcurrentHashMap<>();
    } else {
      debugLogEnabled = false;
      debugLogs = null;
    }
    assert !appView.options().debug;
    ordinalField =
        appView.appInfo().resolveField(factory.enumMembers.ordinalField).getResolutionPair();
  }

  public static int ordinalToUnboxedInt(int ordinal) {
    return ordinal + 1;
  }

  public DexClassAndField getOrdinalField() {
    return ordinalField;
  }

  @Override
  public void updateEnumUnboxingCandidatesInfo() {
    for (DexProgramClass candidate : candidatesToRemoveInWave) {
      enumUnboxingCandidatesInfo.removeCandidate(candidate);
    }
    candidatesToRemoveInWave.clear();
  }

  /**
   * Returns true if {@param enumClass} was marked as being unboxable.
   *
   * <p>Note that, if debug logging is enabled, {@param enumClass} is not marked unboxable until the
   * enum unboxing analysis has finished. This is to ensure completeness of the reason reporting.
   */
  private boolean markEnumAsUnboxable(Reason reason, DexProgramClass enumClass) {
    assert enumClass.isEnum();
    if (!reportFailure(enumClass, reason)) {
      // The failure was not reported, meaning debug logging is disabled.
      candidatesToRemoveInWave.add(enumClass);
      return true;
    }
    return false;
  }

  private void markMethodDependsOnLibraryModelisation(ProgramMethod method) {
    methodsDependingOnLibraryModelisation.add(method, appView.graphLens());
  }

  private DexProgramClass getEnumUnboxingCandidateOrNull(TypeElement lattice) {
    if (lattice.isClassType()) {
      DexType classType = lattice.asClassType().getClassType();
      return getEnumUnboxingCandidateOrNull(classType);
    }
    if (lattice.isArrayType()) {
      ArrayTypeElement arrayType = lattice.asArrayType();
      if (arrayType.getBaseType().isClassType()) {
        return getEnumUnboxingCandidateOrNull(arrayType.getBaseType());
      }
    }
    return null;
  }

  private DexProgramClass getEnumUnboxingCandidateOrNull(DexType type) {
    if (type.isArrayType()) {
      return getEnumUnboxingCandidateOrNull(type.toBaseType(appView.dexItemFactory()));
    }
    if (type.isPrimitiveType() || type.isVoidType()) {
      return null;
    }
    assert type.isClassType();
    return enumUnboxingCandidatesInfo.getCandidateClassOrNull(type);
  }

  @Override
  public void analyzeEnums(IRCode code, MutableMethodConversionOptions conversionOptions) {
    Set<DexType> eligibleEnums = Sets.newIdentityHashSet();
    for (BasicBlock block : code.blocks) {
      for (Instruction instruction : block.getInstructions()) {
        Value outValue = instruction.outValue();
        if (outValue != null) {
          DexProgramClass enumClass =
              getEnumUnboxingCandidateOrNull(outValue.getDynamicUpperBoundType(appView));
          if (enumClass != null) {
            Reason reason = validateEnumUsages(code, outValue, enumClass);
            if (reason == Reason.ELIGIBLE) {
              eligibleEnums.add(enumClass.type);
            }
          }
          if (outValue.getType().isNullType()) {
            addNullDependencies(code, outValue, eligibleEnums);
          }
        } else {
          if (instruction.isInvokeMethod()) {
            DexProgramClass enumClass =
                getEnumUnboxingCandidateOrNull(instruction.asInvokeMethod().getReturnType());
            if (enumClass != null) {
              eligibleEnums.add(enumClass.type);
            }
          }
        }
        switch (instruction.opcode()) {
          case CONST_CLASS:
            analyzeConstClass(instruction.asConstClass(), eligibleEnums, code.context());
            break;
          case CHECK_CAST:
            analyzeCheckCast(instruction.asCheckCast(), eligibleEnums);
            break;
          case INIT_CLASS:
            analyzeInitClass(instruction.asInitClass(), eligibleEnums);
            break;
          case INVOKE_CUSTOM:
            analyzeInvokeCustom(instruction.asInvokeCustom(), eligibleEnums, code.context());
            break;
          case INVOKE_STATIC:
            analyzeInvokeStatic(instruction.asInvokeStatic(), eligibleEnums, code.context());
            break;
          case STATIC_GET:
          case INSTANCE_GET:
          case STATIC_PUT:
          case INSTANCE_PUT:
            analyzeFieldInstruction(
                instruction.asFieldInstruction(), eligibleEnums, code.context());
            break;
          default: // Nothing to do for other instructions.
        }
      }
      for (Phi phi : block.getPhis()) {
        DexProgramClass enumClass = getEnumUnboxingCandidateOrNull(phi.getType());
        if (enumClass != null) {
          Reason reason = validateEnumUsages(code, phi, enumClass);
          if (reason == Reason.ELIGIBLE) {
            eligibleEnums.add(enumClass.type);
          }
        }
        if (phi.getType().isNullType()) {
          addNullDependencies(code, phi, eligibleEnums);
        }
      }
    }
    if (!eligibleEnums.isEmpty()) {
      for (DexType eligibleEnum : eligibleEnums) {
        enumUnboxingCandidatesInfo.addMethodDependency(eligibleEnum, code.context());
      }
    }
    if (methodsDependingOnLibraryModelisation.contains(code.context(), appView.graphLens())) {
      conversionOptions.disablePeepholeOptimizations();
    }
  }

  private void markEnumEligible(DexType type, Set<DexType> eligibleEnums) {
    DexProgramClass enumClass = getEnumUnboxingCandidateOrNull(type);
    if (enumClass != null) {
      eligibleEnums.add(enumClass.getType());
    }
  }

  private void invalidateEnum(DexType type) {
    DexProgramClass enumClass = getEnumUnboxingCandidateOrNull(type);
    if (enumClass != null) {
      markEnumAsUnboxable(Reason.INVALID_INVOKE_CUSTOM, enumClass);
    }
  }

  private void analyzeInvokeCustom(
      InvokeCustom invoke, Set<DexType> eligibleEnums, ProgramMethod context) {
    invoke.getCallSite().getMethodProto().forEachType(t -> markEnumEligible(t, eligibleEnums));
    LambdaDescriptor lambdaDescriptor =
        LambdaDescriptor.tryInfer(invoke.getCallSite(), appView.appInfo(), context);
    if (lambdaDescriptor == null) {
      // Based on lambda we can see that enums cannot be unboxed if used in call site bootstrap
      // arguments, since there might be expectations on overrides. Enums used directly in the
      // method proto should be fine.
      analyzeInvokeCustomParameters(invoke, this::invalidateEnum);
      return;
    }

    analyzeInvokeCustomParameters(invoke, t -> markEnumEligible(t, eligibleEnums));

    lambdaDescriptor.forEachErasedAndEnforcedTypes(
        (erasedType, enforcedType) -> {
          if (erasedType != enforcedType) {
            invalidateEnum(erasedType);
            invalidateEnum(enforcedType);
          }
        });
  }

  private void analyzeInvokeCustomParameters(InvokeCustom invoke, Consumer<DexType> nonHolder) {
    invoke
        .getCallSite()
        .getBootstrapArgs()
        .forEach(
            bootstrapArgument -> {
              if (bootstrapArgument.isDexValueMethodHandle()) {
                DexMethodHandle methodHandle =
                    bootstrapArgument.asDexValueMethodHandle().getValue();
                if (methodHandle.isMethodHandle()) {
                  DexMethod method = methodHandle.asMethod();
                  invalidateEnum(method.getHolderType());
                  method.getProto().forEachType(nonHolder);
                } else {
                  assert methodHandle.isFieldHandle();
                  DexField field = methodHandle.asField();
                  invalidateEnum(field.getHolderType());
                  nonHolder.accept(field.type);
                }
              } else if (bootstrapArgument.isDexValueMethodType()) {
                DexProto proto = bootstrapArgument.asDexValueMethodType().getValue();
                proto.forEachType(nonHolder);
              }
            });
  }

  private void analyzeFieldInstruction(
      FieldInstruction fieldInstruction, Set<DexType> eligibleEnums, ProgramMethod context) {
    DexField field = fieldInstruction.getField();
    DexProgramClass enumClass = getEnumUnboxingCandidateOrNull(field.holder);
    if (enumClass != null) {
      FieldResolutionResult resolutionResult = appView.appInfo().resolveField(field, context);
      if (resolutionResult.isSingleFieldResolutionResult()) {
        eligibleEnums.add(enumClass.getType());
      } else {
        markEnumAsUnboxable(Reason.UNRESOLVABLE_FIELD, enumClass);
      }
    }
  }

  private void analyzeInvokeStatic(
      InvokeStatic invokeStatic, Set<DexType> eligibleEnums, ProgramMethod context) {
    DexMethod invokedMethod = invokeStatic.getInvokedMethod();
    DexProgramClass enumClass = getEnumUnboxingCandidateOrNull(invokedMethod.holder);
    if (enumClass != null) {
      DexClassAndMethod method = invokeStatic.lookupSingleTarget(appView, context);
      if (method != null) {
        eligibleEnums.add(enumClass.type);
      } else {
        markEnumAsUnboxable(Reason.INVALID_INVOKE, enumClass);
      }
    }
  }

  private void analyzeCheckCast(CheckCast checkCast, Set<DexType> eligibleEnums) {
    // Casts to enum array types are fine as long all enum array creations are valid and have valid
    // usages. Since creations of enum arrays are rewritten to primitive int arrays, enum array
    // casts will continue to work after rewriting to int[] casts. Casts that failed with
    // ClassCastException: "T[] cannot be cast to MyEnum[]" will continue to fail, but with "T[]
    // cannot be cast to int[]".
    //
    // Note that strictly speaking, the rewriting from MyEnum[] to int[] could change the semantics
    // of code that would fail with "int[] cannot be cast to MyEnum[]" in the input. However, javac
    // does not allow such code ("incompatible types"), so we should generally not see such code.
    if (checkCast.getType().isArrayType()) {
      return;
    }

    // We are doing a type check, which typically means the in-value is of an upper
    // type and cannot be dealt with.
    // If the cast is on a dynamically typed object, the checkCast can be simply removed.
    // This allows enum array clone and valueOf to work correctly.
    DexProgramClass enumClass =
        getEnumUnboxingCandidateOrNull(checkCast.getType().toBaseType(factory));
    if (enumClass == null) {
      return;
    }
    if (allowCheckCast(checkCast)) {
      eligibleEnums.add(enumClass.type);
      return;
    }
    markEnumAsUnboxable(Reason.DOWN_CAST, enumClass);
  }

  private void analyzeInitClass(InitClass initClass, Set<DexType> eligibleEnums) {
    DexProgramClass enumClass = getEnumUnboxingCandidateOrNull(initClass.getClassValue());
    if (enumClass != null) {
      eligibleEnums.add(enumClass.getType());
    }
  }

  private boolean allowCheckCast(CheckCast checkCast) {
    TypeElement objectType = checkCast.object().getDynamicUpperBoundType(appView);
    return objectType.equalUpToNullability(
        TypeElement.fromDexType(checkCast.getType(), definitelyNotNull(), appView));
  }

  private void analyzeConstClass(
      ConstClass constClass, Set<DexType> eligibleEnums, ProgramMethod context) {
    // We are using the ConstClass of an enum, which typically means the enum cannot be unboxed.
    // We however allow unboxing if the ConstClass is used only:
    // - as an argument to java.lang.reflect.Array#newInstance(java.lang.Class, int[]), to allow
    //   unboxing of:
    //    MyEnum[][] a = new MyEnum[x][y];
    // - as an argument to Enum#valueOf, to allow unboxing of:
    //    MyEnum a = Enum.valueOf(MyEnum.class, "A");
    // - as a receiver for a name method, to allow unboxing of:
    //    MyEnum.class.getName();
    DexType enumType = constClass.getValue();
    if (!enumUnboxingCandidatesInfo.isCandidate(enumType)) {
      return;
    }
    if (constClass.outValue() == null) {
      eligibleEnums.add(enumType);
      return;
    }
    DexProgramClass enumClass = appView.definitionFor(enumType).asProgramClass();
    if (constClass.outValue().hasPhiUsers()) {
      markEnumAsUnboxable(Reason.CONST_CLASS, enumClass);
      return;
    }
    for (Instruction user : constClass.outValue().aliasedUsers()) {
      if (!isLegitimateConstClassUser(user, context, enumClass)) {
        markEnumAsUnboxable(Reason.CONST_CLASS, enumClass);
        return;
      }
    }
    eligibleEnums.add(enumType);
  }

  private boolean isLegitimateConstClassUser(
      Instruction user, ProgramMethod context, DexProgramClass enumClass) {
    if (user.isAssume()) {
      if (user.outValue().hasPhiUsers()) {
        return false;
      }
      return true;
    }

    if (user.isInvokeStatic()) {
      DexClassAndMethod singleTarget = user.asInvokeStatic().lookupSingleTarget(appView, context);
      if (singleTarget == null) {
        return false;
      }
      if (singleTarget.getReference() == factory.enumMembers.valueOf) {
        // The name data is required for the correct mapping from the enum name to the ordinal
        // in the valueOf utility method.
        addRequiredNameData(enumClass);
        markMethodDependsOnLibraryModelisation(context);
        return true;
      }
      if (singleTarget.getReference()
          == factory.javaLangReflectArrayMembers.newInstanceMethodWithDimensions) {
        markMethodDependsOnLibraryModelisation(context);
        return true;
      }
    }

    if (user.isInvokeVirtual()) {
      InvokeVirtual invoke = user.asInvokeVirtual();
      DexMethod invokedMethod = invoke.getInvokedMethod();
      if (invokedMethod == factory.classMethods.desiredAssertionStatus) {
        // Only valid in the enum's class initializer, since the class constant must be rewritten
        // to LocalEnumUtility.class instead of int.class.
        return context.getDefinition().isClassInitializer() && context.getHolder() == enumClass;
      }
      if (isUnboxableNameMethod(invokedMethod)) {
        return true;
      }
    }

    return false;
  }

  private void addRequiredNameData(DexProgramClass enumClass) {
    enumUnboxingCandidatesInfo.addRequiredEnumInstanceFieldData(
        enumClass, factory.enumMembers.nameField);
  }

  private boolean isUnboxableNameMethod(DexMethod method) {
    return method == factory.classMethods.getName
        || method == factory.classMethods.getCanonicalName
        || method == factory.classMethods.getSimpleName;
  }

  private void addNullDependencies(IRCode code, Value nullValue, Set<DexType> eligibleEnums) {
    for (Instruction use : nullValue.uniqueUsers()) {
      if (use.isInvokeMethod()) {
        InvokeMethod invokeMethod = use.asInvokeMethod();
        DexMethod invokedMethod = invokeMethod.getInvokedMethod();
        for (DexType paramType : invokedMethod.proto.parameters.values) {
          if (enumUnboxingCandidatesInfo.isCandidate(paramType)) {
            eligibleEnums.add(paramType);
          }
        }
        if (invokeMethod.isInvokeMethodWithReceiver()
            && invokeMethod.asInvokeMethodWithReceiver().getReceiver() == nullValue) {
          DexProgramClass enumClass = getEnumUnboxingCandidateOrNull(invokedMethod.holder);
          if (enumClass != null) {
            markEnumAsUnboxable(Reason.ENUM_METHOD_CALLED_WITH_NULL_RECEIVER, enumClass);
          }
        }
      } else if (use.isFieldPut()) {
        DexType type = use.asFieldInstruction().getField().type;
        if (enumUnboxingCandidatesInfo.isCandidate(type)) {
          eligibleEnums.add(type);
        }
      } else if (use.isReturn()) {
        DexType returnType = code.method().getReference().proto.returnType;
        if (enumUnboxingCandidatesInfo.isCandidate(returnType)) {
          eligibleEnums.add(returnType);
        }
      }
    }
  }

  private Reason validateEnumUsages(IRCode code, Value value, DexProgramClass enumClass) {
    Reason result = Reason.ELIGIBLE;
    for (Instruction user : value.uniqueUsers()) {
      Reason reason = instructionAllowEnumUnboxing(user, code, enumClass, value);
      if (reason != Reason.ELIGIBLE) {
        if (markEnumAsUnboxable(reason, enumClass)) {
          return reason;
        }
        // Record that the enum is ineligible, and continue analysis to collect all reasons for
        // debugging.
        result = reason;
      }
    }
    for (Phi phi : value.uniquePhiUsers()) {
      for (Value operand : phi.getOperands()) {
        if (!operand.getType().isNullType()
            && getEnumUnboxingCandidateOrNull(operand.getType()) != enumClass) {
          // All reported reasons from here will be the same (INVALID_PHI), so just return
          // immediately.
          markEnumAsUnboxable(Reason.INVALID_PHI, enumClass);
          return Reason.INVALID_PHI;
        }
      }
    }
    return result;
  }

  @Override
  public void prepareForPrimaryOptimizationPass(GraphLens graphLensForPrimaryOptimizationPass) {
    assert appView.graphLens() == graphLensForPrimaryOptimizationPass;
    initializeCheckNotNullMethods(graphLensForPrimaryOptimizationPass);
    initializeEnumUnboxingCandidates(graphLensForPrimaryOptimizationPass);
  }

  private void initializeCheckNotNullMethods(GraphLens graphLensForPrimaryOptimizationPass) {
    assert checkNotNullMethodsBuilder == null;
    checkNotNullMethodsBuilder =
        LongLivedProgramMethodMapBuilder.createConcurrentBuilderForNonConcurrentMap(
            graphLensForPrimaryOptimizationPass);
  }

  private void initializeEnumUnboxingCandidates(GraphLens graphLensForPrimaryOptimizationPass) {
    assert enumUnboxingCandidatesInfo == null;
    enumUnboxingCandidatesInfo =
        new EnumUnboxingCandidateAnalysis(appView, this)
            .findCandidates(graphLensForPrimaryOptimizationPass);
    methodsDependingOnLibraryModelisation =
        LongLivedProgramMethodSetBuilder.createConcurrentForIdentitySet(
            graphLensForPrimaryOptimizationPass);
  }

  @Override
  public void rewriteWithLens() {
    methodsDependingOnLibraryModelisation =
        methodsDependingOnLibraryModelisation.rewrittenWithLens(appView.graphLens());
  }

  @Override
  public void unboxEnums(
      AppView<AppInfoWithLiveness> appView,
      IRConverter converter,
      Builder postMethodProcessorBuilder,
      ExecutorService executorService,
      OptimizationFeedbackDelayed feedback)
      throws ExecutionException {
    assert feedback.noUpdatesLeft();

    assert candidatesToRemoveInWave.isEmpty();
    EnumDataMap enumDataMap = finishAnalysis();
    assert candidatesToRemoveInWave.isEmpty();

    // At this point the enum unboxing candidates are no longer candidates, they will all be
    // unboxed. We extract the now immutable enums to unbox information and clear the candidate
    // info.
    appView.setUnboxedEnums(enumDataMap);

    if (enumUnboxingCandidatesInfo.isEmpty()) {
      assert enumDataMap.isEmpty();
      return;
    }

    GraphLens previousLens = appView.graphLens();
    ImmutableSet<DexType> enumsToUnbox = enumUnboxingCandidatesInfo.candidates();
    ImmutableSet<DexProgramClass> enumClassesToUnbox =
        enumUnboxingCandidatesInfo.candidateClasses();
    LongLivedProgramMethodSetBuilder<ProgramMethodSet> dependencies =
        enumUnboxingCandidatesInfo.allMethodDependencies();
    enumUnboxingCandidatesInfo.clear();
    // Update keep info on any of the enum methods of the removed classes.
    updateKeepInfo(enumsToUnbox);

    EnumUnboxingUtilityClasses utilityClasses =
        EnumUnboxingUtilityClasses.builder(appView)
            .synthesizeEnumUnboxingUtilityClasses(enumClassesToUnbox, enumDataMap)
            .build(converter, executorService);

    // Fixup the application.
    ProgramMethodMap<Set<DexProgramClass>> checkNotNullMethods =
        checkNotNullMethodsBuilder
            .rewrittenWithLens(appView, (enumClasses, appliedGraphLens) -> enumClasses)
            .build(appView, builder -> builder.build(appView));
    checkNotNullMethods.removeIf(
        (checkNotNullMethod, ignore) ->
            !checkNotNullMethod
                .getOptimizationInfo()
                .getEnumUnboxerMethodClassification()
                .isCheckNotNullClassification());

    EnumUnboxingTreeFixer.Result treeFixerResult =
        new EnumUnboxingTreeFixer(
                appView, checkNotNullMethods, enumDataMap, enumClassesToUnbox, utilityClasses)
            .fixupTypeReferences(converter, executorService);
    EnumUnboxingLens enumUnboxingLens = treeFixerResult.getLens();

    // Enqueue the (lens rewritten) methods that require reprocessing.
    //
    // Note that the reprocessing set must be rewritten to the new enum unboxing lens before pruning
    // the builders with the methods removed by the tree fixer (since these methods references are
    // already fully lens rewritten).
    postMethodProcessorBuilder
        .rewrittenWithLens(appView)
        .removeAll(treeFixerResult.getPrunedItems().getRemovedMethods())
        .merge(
            dependencies
                .rewrittenWithLens(appView)
                .removeAll(treeFixerResult.getPrunedItems().getRemovedMethods()))
        .merge(
            methodsDependingOnLibraryModelisation
                .rewrittenWithLens(appView)
                .removeAll(treeFixerResult.getPrunedItems().getRemovedMethods()));
    methodsDependingOnLibraryModelisation.clear();

    updateOptimizationInfos(executorService, feedback, treeFixerResult, previousLens);

    enumUnboxerRewriter =
        new EnumUnboxingRewriter(
            appView,
            treeFixerResult.getCheckNotNullToCheckNotZeroMapping(),
            enumUnboxingLens,
            enumDataMap,
            utilityClasses);
  }

  private void updateOptimizationInfos(
      ExecutorService executorService,
      OptimizationFeedbackDelayed feedback,
      EnumUnboxingTreeFixer.Result treeFixerResult,
      GraphLens previousLens)
      throws ExecutionException {
    NonIdentityGraphLens graphLens = appView.graphLens().asNonIdentityLens();
    assert graphLens.isEnumUnboxerLens();

    GraphLens codeLens = graphLens.getPrevious();
    assert codeLens == previousLens;

    feedback.fixupOptimizationInfos(
        appView,
        executorService,
        new OptimizationInfoFixer() {
          @Override
          public void fixup(DexEncodedField field, MutableFieldOptimizationInfo optimizationInfo) {
            optimizationInfo
                .fixupClassTypeReferences(appView, graphLens)
                .fixupAbstractValue(appView, graphLens, codeLens);
          }

          @Override
          public void fixup(
              DexEncodedMethod method, MutableMethodOptimizationInfo optimizationInfo) {
            optimizationInfo
                .fixupClassTypeReferences(appView, graphLens)
                .fixupAbstractReturnValue(appView, graphLens, codeLens)
                .fixupInstanceInitializerInfo(
                    appView, graphLens, codeLens, treeFixerResult.getPrunedItems());

            // Clear the enum unboxer method classification for check-not-null methods (these
            // classifications are transferred to the synthesized check-not-zero methods by now).
            if (!treeFixerResult
                .getCheckNotNullToCheckNotZeroMapping()
                .containsValue(method.getReference())) {
              optimizationInfo.unsetEnumUnboxerMethodClassification();
            }
          }
        });
  }

  private void updateKeepInfo(Set<DexType> enumsToUnbox) {
    KeepInfoCollection keepInfo = appView.appInfo().getKeepInfo();
    keepInfo.mutate(
        mutator ->
            mutator.removeKeepInfoForPrunedItems(
                PrunedItems.builder().setRemovedClasses(enumsToUnbox).build()));
  }

  public EnumDataMap finishAnalysis() {
    analyzeInitializers();
    updateEnumUnboxingCandidatesInfo();
    EnumDataMap enumDataMap = analyzeEnumInstances();
    if (debugLogEnabled) {
      // Remove all enums that have been reported as being unboxable.
      debugLogs.keySet().forEach(enumUnboxingCandidatesInfo::removeCandidate);
      reportEnumsAnalysis();
    }
    assert enumDataMap.getUnboxedEnums().size() == enumUnboxingCandidatesInfo.candidates().size();
    return enumDataMap;
  }

  private EnumDataMap analyzeEnumInstances() {
    ImmutableMap.Builder<DexType, EnumData> builder = ImmutableMap.builder();
    enumUnboxingCandidatesInfo.forEachCandidateAndRequiredInstanceFieldData(
        (enumClass, instanceFields) -> {
          EnumData data = buildData(enumClass, instanceFields);
          if (data == null) {
            // Reason is already reported at this point.
            enumUnboxingCandidatesInfo.removeCandidate(enumClass);
            return;
          }
          if (!debugLogEnabled || !debugLogs.containsKey(enumClass.getType())) {
            builder.put(enumClass.type, data);
          }
        });
    staticFieldValuesMap.clear();
    return new EnumDataMap(builder.build());
  }

  private EnumData buildData(DexProgramClass enumClass, Set<DexField> instanceFields) {
    if (!enumClass.hasStaticFields()) {
      return new EnumData(ImmutableMap.of(), ImmutableMap.of(), ImmutableSet.of(), -1);
    }

    // This map holds all the accessible fields to their unboxed value, so we can remap the field
    // read to the unboxed value.
    ImmutableMap.Builder<DexField, Integer> unboxedValues = ImmutableMap.builder();
    // This maps the ordinal to the object state, note that some fields may have been removed,
    // hence the entry is in this map but not the enumToOrdinalMap.
    Int2ReferenceMap<ObjectState> ordinalToObjectState = new Int2ReferenceArrayMap<>();
    // Any fields matching the expected $VALUES content can be recorded here, they have however
    // all the same content.
    ImmutableSet.Builder<DexField> valuesField = ImmutableSet.builder();
    EnumValuesObjectState valuesContents = null;

    EnumStaticFieldValues enumStaticFieldValues = staticFieldValuesMap.get(enumClass.type);
    if (enumStaticFieldValues == null) {
      reportFailure(enumClass, new MissingEnumStaticFieldValuesReason());
      return null;
    }

    // Step 1: We iterate over the field to find direct enum instance information and the values
    // fields.
    for (DexEncodedField staticField : enumClass.staticFields()) {
      if (factory.enumMembers.isEnumField(staticField, enumClass.type)) {
        ObjectState enumState =
            enumStaticFieldValues.getObjectStateForPossiblyPinnedField(staticField.getReference());
        if (enumState == null) {
          if (staticField.getOptimizationInfo().isDead()) {
            // We don't care about unused field data.
            continue;
          }
          // We could not track the content of that field. We bail out.
          reportFailure(
              enumClass, new MissingObjectStateForEnumInstanceReason(staticField.getReference()));
          return null;
        }
        OptionalInt optionalOrdinal = getOrdinal(enumState);
        if (!optionalOrdinal.isPresent()) {
          reportFailure(
              enumClass,
              new MissingInstanceFieldValueForEnumInstanceReason(
                  staticField.getReference(), factory.enumMembers.ordinalField));
          return null;
        }
        int ordinal = optionalOrdinal.getAsInt();
        unboxedValues.put(staticField.getReference(), ordinalToUnboxedInt(ordinal));
        ordinalToObjectState.put(ordinal, enumState);
      } else if (factory.enumMembers.isValuesFieldCandidate(staticField, enumClass.type)) {
        ObjectState valuesState =
            enumStaticFieldValues.getObjectStateForPossiblyPinnedField(staticField.getReference());
        if (valuesState == null) {
          if (staticField.getOptimizationInfo().isDead()) {
            // We don't care about unused field data.
            continue;
          }
          // We could not track the content of that field. We bail out.
          // We could not track the content of that field, and the field could be a values field.
          // We conservatively bail out.
          reportFailure(
              enumClass, new MissingContentsForEnumValuesArrayReason(staticField.getReference()));
          return null;
        }
        assert valuesState.isEnumValuesObjectState();
        assert valuesContents == null
            || valuesContents.equals(valuesState.asEnumValuesObjectState());
        valuesContents = valuesState.asEnumValuesObjectState();
        valuesField.add(staticField.getReference());
      }
    }

    // Step 2: We complete the information based on the values content, since some enum instances
    // may be reachable only though the $VALUES field.
    if (valuesContents != null) {
      for (int ordinal = 0; ordinal < valuesContents.getEnumValuesSize(); ordinal++) {
        if (!ordinalToObjectState.containsKey(ordinal)) {
          ObjectState enumState = valuesContents.getObjectStateForOrdinal(ordinal);
          if (enumState.isEmpty()) {
            // If $VALUES is used, we need data for all enums, at least the ordinal.
            return null;
          }
          assert getOrdinal(enumState).isPresent();
          assert getOrdinal(enumState).getAsInt() == ordinal;
          ordinalToObjectState.put(ordinal, enumState);
        }
      }
    }

    // The ordinalToObjectState map may have holes at this point, if some enum instances are never
    // used ($VALUES unused or removed, and enum instance field unused or removed), it contains
    // only data for reachable enum instance, that is what we're interested in.
    ImmutableMap<DexField, EnumInstanceFieldKnownData> instanceFieldsData =
        computeRequiredEnumInstanceFieldsData(enumClass, instanceFields, ordinalToObjectState);
    if (instanceFieldsData == null) {
      return null;
    }

    return new EnumData(
        instanceFieldsData,
        unboxedValues.build(),
        valuesField.build(),
        valuesContents == null ? EnumData.INVALID_VALUES_SIZE : valuesContents.getEnumValuesSize());
  }

  private ImmutableMap<DexField, EnumInstanceFieldKnownData> computeRequiredEnumInstanceFieldsData(
      DexProgramClass enumClass,
      Set<DexField> instanceFields,
      Int2ReferenceMap<ObjectState> ordinalToObjectState) {
    ImmutableMap.Builder<DexField, EnumInstanceFieldKnownData> builder = ImmutableMap.builder();
    for (DexField instanceField : instanceFields) {
      EnumInstanceFieldData fieldData =
          computeRequiredEnumInstanceFieldData(instanceField, enumClass, ordinalToObjectState);
      if (fieldData.isUnknown()) {
        if (!debugLogEnabled) {
          return null;
        }
        builder = null;
      }
      if (builder != null) {
        builder.put(instanceField, fieldData.asEnumFieldKnownData());
      }
    }
    return builder != null ? builder.build() : null;
  }

  private EnumInstanceFieldData computeRequiredEnumInstanceFieldData(
      DexField instanceField,
      DexProgramClass enumClass,
      Int2ReferenceMap<ObjectState> ordinalToObjectState) {
    DexEncodedField encodedInstanceField =
        appView.appInfo().resolveFieldOn(enumClass, instanceField).getResolvedField();
    assert encodedInstanceField != null;
    boolean canBeOrdinal = instanceField.type.isIntType();
    ImmutableInt2ReferenceSortedMap.Builder<AbstractValue> data =
        ImmutableInt2ReferenceSortedMap.builder();
    for (Integer ordinal : ordinalToObjectState.keySet()) {
      ObjectState state = ordinalToObjectState.get(ordinal);
      AbstractValue fieldValue = state.getAbstractFieldValue(encodedInstanceField);
      if (!fieldValue.isSingleValue()) {
        reportFailure(
            enumClass, new MissingInstanceFieldValueForEnumInstanceReason(ordinal, instanceField));
        return EnumInstanceFieldUnknownData.getInstance();
      }
      if (!(fieldValue.isSingleNumberValue() || fieldValue.isSingleStringValue())) {
        reportFailure(
            enumClass,
            new UnsupportedInstanceFieldValueForEnumInstanceReason(ordinal, instanceField));
        return EnumInstanceFieldUnknownData.getInstance();
      }
      data.put(ordinalToUnboxedInt(ordinal), fieldValue);
      if (canBeOrdinal) {
        assert fieldValue.isSingleNumberValue();
        int computedValue = fieldValue.asSingleNumberValue().getIntValue();
        if (computedValue != ordinal) {
          canBeOrdinal = false;
        }
      }
    }
    if (canBeOrdinal) {
      return new EnumInstanceFieldOrdinalData();
    }
    return new EnumInstanceFieldMappingData(data.build());
  }

  private OptionalInt getOrdinal(ObjectState state) {
    AbstractValue field = state.getAbstractFieldValue(getOrdinalField().getDefinition());
    if (field.isSingleNumberValue()) {
      return OptionalInt.of(field.asSingleNumberValue().getIntValue());
    }
    return OptionalInt.empty();
  }

  @Override
  public void recordEnumState(DexProgramClass clazz, StaticFieldValues staticFieldValues) {
    if (staticFieldValues == null || !staticFieldValues.isEnumStaticFieldValues()) {
      return;
    }
    assert clazz.isEnum();
    EnumStaticFieldValues enumStaticFieldValues = staticFieldValues.asEnumStaticFieldValues();
    if (getEnumUnboxingCandidateOrNull(clazz.type) != null) {
      staticFieldValuesMap.put(clazz.type, enumStaticFieldValues);
    }
  }

  private void analyzeInitializers() {
    enumUnboxingCandidatesInfo.forEachCandidate(
        enumClass -> {
          for (DexEncodedMethod directMethod : enumClass.directMethods()) {
            if (directMethod.isInstanceInitializer()) {
              if (directMethod
                  .getOptimizationInfo()
                  .getContextInsensitiveInstanceInitializerInfo()
                  .mayHaveOtherSideEffectsThanInstanceFieldAssignments()) {
                if (markEnumAsUnboxable(Reason.INVALID_INIT, enumClass)) {
                  break;
                }
              }
            }
          }
          if (enumClass.classInitializationMayHaveSideEffects(appView)) {
            markEnumAsUnboxable(Reason.INVALID_CLINIT, enumClass);
          }
        });
  }

  private Reason instructionAllowEnumUnboxing(
      Instruction instruction, IRCode code, DexProgramClass enumClass, Value enumValue) {
    ProgramMethod context = code.context();
    switch (instruction.opcode()) {
      case ASSUME:
        return analyzeAssumeUser(instruction.asAssume(), code, context, enumClass, enumValue);
      case ARRAY_GET:
        return analyzeArrayGetUser(instruction.asArrayGet(), code, context, enumClass, enumValue);
      case ARRAY_LENGTH:
        return analyzeArrayLengthUser(
            instruction.asArrayLength(), code, context, enumClass, enumValue);
      case ARRAY_PUT:
        return analyzeArrayPutUser(instruction.asArrayPut(), code, context, enumClass, enumValue);
      case CHECK_CAST:
        return analyzeCheckCastUser(instruction.asCheckCast(), code, context, enumClass, enumValue);
      case IF:
        return analyzeIfUser(instruction.asIf(), code, context, enumClass, enumValue);
      case INSTANCE_GET:
        return analyzeInstanceGetUser(
            instruction.asInstanceGet(), code, context, enumClass, enumValue);
      case INSTANCE_PUT:
        return analyzeFieldPutUser(
            instruction.asInstancePut(), code, context, enumClass, enumValue);
      case INVOKE_DIRECT:
      case INVOKE_INTERFACE:
      case INVOKE_STATIC:
      case INVOKE_SUPER:
      case INVOKE_VIRTUAL:
        return analyzeInvokeUser(instruction.asInvokeMethod(), code, context, enumClass, enumValue);
      case RETURN:
        return analyzeReturnUser(instruction.asReturn(), code, context, enumClass, enumValue);
      case STATIC_PUT:
        return analyzeFieldPutUser(instruction.asStaticPut(), code, context, enumClass, enumValue);
      default:
        return Reason.OTHER_UNSUPPORTED_INSTRUCTION;
    }
  }

  private Reason analyzeAssumeUser(
      Assume assume,
      IRCode code,
      ProgramMethod context,
      DexProgramClass enumClass,
      Value enumValue) {
    return validateEnumUsages(code, assume.outValue(), enumClass);
  }

  private Reason analyzeArrayGetUser(
      ArrayGet arrayGet,
      IRCode code,
      ProgramMethod context,
      DexProgramClass enumClass,
      Value enumValue) {
    // MyEnum[] array = ...; array[0]; is valid.
    return Reason.ELIGIBLE;
  }

  private Reason analyzeArrayLengthUser(
      ArrayLength arrayLength,
      IRCode code,
      ProgramMethod context,
      DexProgramClass enumClass,
      Value enumValue) {
    // MyEnum[] array = ...; array.length; is valid.
    return Reason.ELIGIBLE;
  }

  private Reason analyzeArrayPutUser(
      ArrayPut arrayPut,
      IRCode code,
      ProgramMethod context,
      DexProgramClass enumClass,
      Value enumValue) {
    // MyEnum[] array; array[0] = MyEnum.A; is valid.
    // MyEnum[][] array2d; MyEnum[] array; array2d[0] = array; is valid.
    // MyEnum[]^N array; MyEnum[]^(N-1) element; array[0] = element; is valid.
    // We need to prove that the value to put in and the array have correct types.
    assert arrayPut.getMemberType() == MemberType.OBJECT;
    TypeElement arrayType = arrayPut.array().getType();
    assert arrayType.isArrayType();
    assert arrayType.asArrayType().getBaseType().isClassType();
    ClassTypeElement arrayBaseType = arrayType.asArrayType().getBaseType().asClassType();
    TypeElement valueBaseType = arrayPut.value().getType();
    if (valueBaseType.isArrayType()) {
      assert valueBaseType.asArrayType().getBaseType().isClassType();
      assert valueBaseType.asArrayType().getNesting() == arrayType.asArrayType().getNesting() - 1;
      valueBaseType = valueBaseType.asArrayType().getBaseType();
    }
    if (arrayBaseType.equalUpToNullability(valueBaseType)
        && arrayBaseType.getClassType() == enumClass.type) {
      return Reason.ELIGIBLE;
    }
    return Reason.INVALID_ARRAY_PUT;
  }

  private Reason analyzeCheckCastUser(
      CheckCast checkCast,
      IRCode code,
      ProgramMethod context,
      DexProgramClass enumClass,
      Value enumValue) {
    if (allowCheckCast(checkCast)) {
      return Reason.ELIGIBLE;
    }
    return Reason.DOWN_CAST;
  }

  // A field put is valid only if the field is not on an enum, and the field type and the valuePut
  // have identical enum type.
  private Reason analyzeFieldPutUser(
      FieldInstruction fieldPut,
      IRCode code,
      ProgramMethod context,
      DexProgramClass enumClass,
      Value enumValue) {
    assert fieldPut.isInstancePut() || fieldPut.isStaticPut();
    DexEncodedField field = appView.appInfo().resolveField(fieldPut.getField()).getResolvedField();
    if (field == null) {
      return Reason.INVALID_FIELD_PUT;
    }
    DexProgramClass dexClass = appView.programDefinitionFor(field.getHolderType(), code.context());
    if (dexClass == null) {
      return Reason.INVALID_FIELD_PUT;
    }
    if (fieldPut.isInstancePut() && fieldPut.asInstancePut().object() == enumValue) {
      return Reason.ELIGIBLE;
    }
    // The put value has to be of the field type.
    if (field.getReference().type.toBaseType(factory) != enumClass.type) {
      return Reason.TYPE_MISMATCH_FIELD_PUT;
    }
    return Reason.ELIGIBLE;
  }

  // An If using enum as inValue is valid if it matches e == null
  // or e == X with X of same enum type as e. Ex: if (e == MyEnum.A).
  private Reason analyzeIfUser(
      If theIf, IRCode code, ProgramMethod context, DexProgramClass enumClass, Value enumValue) {
    assert (theIf.getType() == If.Type.EQ || theIf.getType() == If.Type.NE)
        : "Comparing a reference with " + theIf.getType().toString();
    // e == null.
    if (theIf.isZeroTest()) {
      return Reason.ELIGIBLE;
    }
    // e == MyEnum.X
    TypeElement leftType = theIf.lhs().getType();
    TypeElement rightType = theIf.rhs().getType();
    if (leftType.equalUpToNullability(rightType)) {
      assert leftType.isClassType();
      assert leftType.asClassType().getClassType() == enumClass.type;
      return Reason.ELIGIBLE;
    }
    return Reason.INVALID_IF_TYPES;
  }

  private Reason analyzeInstanceGetUser(
      InstanceGet instanceGet,
      IRCode code,
      ProgramMethod context,
      DexProgramClass enumClass,
      Value enumValue) {
    assert instanceGet.getField().holder == enumClass.type;
    DexField field = instanceGet.getField();
    enumUnboxingCandidatesInfo.addRequiredEnumInstanceFieldData(enumClass, field);
    return Reason.ELIGIBLE;
  }

  // All invokes in the library are invalid, besides a few cherry picked cases such as ordinal().
  private Reason analyzeInvokeUser(
      InvokeMethod invoke,
      IRCode code,
      ProgramMethod context,
      DexProgramClass enumClass,
      Value enumValue) {
    if (invoke.getInvokedMethod().holder.isArrayType()) {
      // The only valid methods is clone for values() to be correct.
      if (invoke.getInvokedMethod().name == factory.cloneMethodName) {
        return Reason.ELIGIBLE;
      }
      return Reason.INVALID_INVOKE_ON_ARRAY;
    }
    DexClassAndMethod singleTarget = invoke.lookupSingleTarget(appView, code.context());
    if (singleTarget == null) {
      return Reason.INVALID_INVOKE;
    }
    DexMethod singleTargetReference = singleTarget.getReference();
    DexClass targetHolder = singleTarget.getHolder();
    if (targetHolder.isProgramClass()) {
      if (targetHolder.isEnum() && singleTarget.getDefinition().isInstanceInitializer()) {
        // The enum instance initializer is only allowed to be called from an initializer of the
        // enum itself.
        if (code.context().getHolder() != targetHolder || !code.method().isInitializer()) {
          return Reason.INVALID_INIT;
        }
        if (code.method().isInstanceInitializer() && !invoke.getFirstArgument().isThis()) {
          return Reason.INVALID_INIT;
        }
        return Reason.ELIGIBLE;
      }

      // Check if this is a checkNotNull() user. In this case, we can create a copy of the method
      // that takes an int instead of java.lang.Object and call that method instead.
      EnumUnboxerMethodClassification classification =
          singleTarget.getOptimizationInfo().getEnumUnboxerMethodClassification();
      if (classification.isCheckNotNullClassification()) {
        CheckNotNullEnumUnboxerMethodClassification checkNotNullClassification =
            classification.asCheckNotNullClassification();
        if (checkNotNullClassification.isUseEligibleForUnboxing(
            invoke.asInvokeStatic(), enumValue)) {
          GraphLens graphLens = appView.graphLens();
          checkNotNullMethodsBuilder
              .computeIfAbsent(
                  singleTarget.asProgramMethod(),
                  ignoreKey(
                      () ->
                          LongLivedClassSetBuilder.createConcurrentBuilderForIdentitySet(
                              graphLens)),
                  graphLens)
              .add(enumClass, graphLens);
          return Reason.ELIGIBLE;
        }
      }

      // Check that the enum-value only flows into parameters whose type exactly matches the
      // enum's type.
      for (int i = 0; i < singleTarget.getParameters().size(); i++) {
        if (invoke.getArgumentForParameter(i) == enumValue
            && singleTarget.getParameter(i).toBaseType(factory) != enumClass.getType()) {
          return new IllegalInvokeWithImpreciseParameterTypeReason(singleTargetReference);
        }
      }
      if (invoke.isInvokeMethodWithReceiver()) {
        Value receiver = invoke.asInvokeMethodWithReceiver().getReceiver();
        if (receiver == enumValue && targetHolder.isInterface()) {
          return Reason.DEFAULT_METHOD_INVOKE;
        }
      }
      return Reason.ELIGIBLE;
    }

    if (targetHolder.isClasspathClass()) {
      return Reason.INVALID_INVOKE_CLASSPATH;
    }

    assert targetHolder.isLibraryClass();

    Reason reason =
        analyzeLibraryInvoke(
            invoke, code, context, enumClass, enumValue, singleTargetReference, targetHolder);

    if (reason == Reason.ELIGIBLE) {
      markMethodDependsOnLibraryModelisation(context);
    }

    return reason;
  }

  private Reason analyzeLibraryInvoke(
      InvokeMethod invoke,
      IRCode code,
      ProgramMethod context,
      DexProgramClass enumClass,
      Value enumValue,
      DexMethod singleTargetReference,
      DexClass targetHolder) {
    // Calls to java.lang.Enum.
    if (targetHolder.getType() == factory.enumType) {
      // TODO(b/147860220): EnumSet and EnumMap may be interesting to model.
      if (singleTargetReference == factory.enumMembers.compareTo
          || singleTargetReference == factory.enumMembers.compareToWithObject) {
        DexProgramClass otherEnumClass =
            getEnumUnboxingCandidateOrNull(invoke.getLastArgument().getType());
        if (otherEnumClass == enumClass || invoke.getLastArgument().getType().isNullType()) {
          return Reason.ELIGIBLE;
        }
      } else if (singleTargetReference == factory.enumMembers.equals) {
        return Reason.ELIGIBLE;
      } else if (singleTargetReference == factory.enumMembers.nameMethod
          || singleTargetReference == factory.enumMembers.toString) {
        assert invoke.asInvokeMethodWithReceiver().getReceiver() == enumValue;
        addRequiredNameData(enumClass);
        return Reason.ELIGIBLE;
      } else if (singleTargetReference == factory.enumMembers.ordinalMethod) {
        return Reason.ELIGIBLE;
      } else if (singleTargetReference == factory.enumMembers.hashCode) {
        return Reason.ELIGIBLE;
      } else if (singleTargetReference == factory.enumMembers.constructor) {
        // Enum constructor call is allowed only if called from an enum initializer.
        if (code.method().isInstanceInitializer() && code.context().getHolder() == enumClass) {
          return Reason.ELIGIBLE;
        }
      }
      return new UnsupportedLibraryInvokeReason(singleTargetReference);
    }

    // Calls to java.lang.Object.
    if (targetHolder.getType() == factory.objectType) {
      // Object#getClass without outValue is important since R8 rewrites explicit null checks to
      // such instructions.
      if (singleTargetReference == factory.objectMembers.getClass && invoke.hasUnusedOutValue()) {
        // This is a hidden null check.
        return Reason.ELIGIBLE;
      }
      return new UnsupportedLibraryInvokeReason(singleTargetReference);
    }

    // Calls to java.lang.Objects.
    if (targetHolder.getType() == factory.objectsType) {
      // Objects#requireNonNull is important since R8 rewrites explicit null checks to such
      // instructions.
      if (singleTargetReference == factory.objectsMethods.requireNonNull
          || singleTargetReference == factory.objectsMethods.requireNonNullWithMessage) {
        return Reason.ELIGIBLE;
      }
      return new UnsupportedLibraryInvokeReason(singleTargetReference);
    }

    // Calls to java.lang.String.
    if (targetHolder.getType() == factory.stringType) {
      if (singleTargetReference == factory.stringMembers.valueOf) {
        addRequiredNameData(enumClass);
        return Reason.ELIGIBLE;
      }
      return new UnsupportedLibraryInvokeReason(singleTargetReference);
    }

    // Calls to java.lang.StringBuilder and java.lang.StringBuffer.
    if (targetHolder.getType() == factory.stringBuilderType
        || targetHolder.getType() == factory.stringBufferType) {
      if (singleTargetReference == factory.stringBuilderMethods.appendObject
          || singleTargetReference == factory.stringBufferMethods.appendObject) {
        addRequiredNameData(enumClass);
        return Reason.ELIGIBLE;
      }
      return new UnsupportedLibraryInvokeReason(singleTargetReference);
    }

    // Calls to java.lang.System.
    if (targetHolder.getType() == factory.javaLangSystemType) {
      if (singleTargetReference == factory.javaLangSystemMethods.arraycopy) {
        // Important for Kotlin 1.5 enums, which use arraycopy to create a copy of $VALUES instead
        // of int[].clone().
        return Reason.ELIGIBLE;
      }
      if (singleTargetReference == factory.javaLangSystemMethods.identityHashCode) {
        // Important for proto enum unboxing.
        return Reason.ELIGIBLE;
      }
      return new UnsupportedLibraryInvokeReason(singleTargetReference);
    }

    // Unsupported holder.
    return new UnsupportedLibraryInvokeReason(singleTargetReference);
  }

  // Return is used for valueOf methods.
  private Reason analyzeReturnUser(
      Return theReturn,
      IRCode code,
      ProgramMethod context,
      DexProgramClass enumClass,
      Value enumValue) {
    DexType returnType = context.getReturnType();
    if (returnType != enumClass.type && returnType.toBaseType(factory) != enumClass.type) {
      return Reason.IMPLICIT_UP_CAST_IN_RETURN;
    }
    return Reason.ELIGIBLE;
  }

  private void reportEnumsAnalysis() {
    assert debugLogEnabled;
    Reporter reporter = appView.reporter();
    Set<DexType> candidates = enumUnboxingCandidatesInfo.candidates();
    reporter.info(
        new StringDiagnostic(
            "Unboxed " + candidates.size() + " enums: " + Arrays.toString(candidates.toArray())));

    StringBuilder sb =
        new StringBuilder("Unable to unbox ")
            .append(debugLogs.size())
            .append(" enums.")
            .append(System.lineSeparator())
            .append(System.lineSeparator());

    // Sort by the number of reasons that prevent enum unboxing.
    TreeMap<DexType, List<Reason>> sortedDebugLogs =
        new TreeMap<>(
            Comparator.<DexType>comparingInt(x -> debugLogs.get(x).size())
                .thenComparing(Function.identity()));
    sortedDebugLogs.putAll(debugLogs);

    // Print the pinned enums and remove them from further reporting.
    List<DexType> pinned = new ArrayList<>();
    Iterator<Entry<DexType, List<Reason>>> sortedDebugLogIterator =
        sortedDebugLogs.entrySet().iterator();
    while (sortedDebugLogIterator.hasNext()) {
      Entry<DexType, List<Reason>> entry = sortedDebugLogIterator.next();
      List<Reason> reasons = entry.getValue();
      if (reasons.size() > 1) {
        break;
      }
      if (reasons.get(0) == Reason.PINNED) {
        pinned.add(entry.getKey());
        sortedDebugLogIterator.remove();
      }
    }
    if (!pinned.isEmpty()) {
      sb.append("Pinned: ").append(Arrays.toString(pinned.toArray()));
    }

    // Print the reasons for each unboxable enum.
    sortedDebugLogs.forEach(
        (type, reasons) -> {
          sb.append(type).append(" (").append(reasons.size()).append(" reasons):");
          HashMultiset.create(reasons)
              .forEachEntry(
                  (reason, count) ->
                      sb.append(System.lineSeparator())
                          .append(" - ")
                          .append(reason)
                          .append(" (")
                          .append(count)
                          .append(")"));
          sb.append(System.lineSeparator());
        });

    sb.append(System.lineSeparator());

    // Print information about how often a given Reason kind prevents enum unboxing.
    Object2IntMap<Object> reasonKindCount = new Object2IntOpenHashMap<>();
    debugLogs.forEach(
        (type, reasons) ->
            reasons.forEach(
                reason ->
                    reasonKindCount.put(reason.getKind(), reasonKindCount.getInt(reason) + 1)));
    List<Object> differentReasonKinds = new ArrayList<>(reasonKindCount.keySet());
    differentReasonKinds.sort(
        (reasonKind, other) -> {
          int freq = reasonKindCount.getInt(reasonKind) - reasonKindCount.getInt(other);
          return freq != 0
              ? freq
              : System.identityHashCode(reasonKind) - System.identityHashCode(other);
        });
    differentReasonKinds.forEach(
        reasonKind ->
            sb.append(reasonKind)
                .append(" (")
                .append(reasonKindCount.getInt(reasonKind))
                .append(")")
                .append(System.lineSeparator()));

    reporter.info(new StringDiagnostic(sb.toString()));
  }

  boolean reportFailure(DexProgramClass enumClass, Reason reason) {
    return reportFailure(enumClass.getType(), reason);
  }

  /** Returns true if the failure was reported. */
  boolean reportFailure(DexType enumType, Reason reason) {
    if (debugLogEnabled) {
      debugLogs
          .computeIfAbsent(enumType, ignore -> Collections.synchronizedList(new ArrayList<>()))
          .add(reason);
      return true;
    }
    return false;
  }

  @Override
  public void onMethodPruned(ProgramMethod method) {
    onMethodCodePruned(method);
  }

  @Override
  public void onMethodCodePruned(ProgramMethod method) {
    enumUnboxingCandidatesInfo.addPrunedMethod(method);
    methodsDependingOnLibraryModelisation.remove(method.getReference(), appView.graphLens());
  }

  @Override
  public Set<Phi> rewriteCode(
      IRCode code,
      MethodProcessor methodProcessor,
      RewrittenPrototypeDescription prototypeChanges) {
    // This has no effect during primary processing since the enumUnboxerRewriter is set
    // in between primary and post processing.
    if (enumUnboxerRewriter != null) {
      return enumUnboxerRewriter.rewriteCode(code, methodProcessor, prototypeChanges);
    }
    return Sets.newIdentityHashSet();
  }

  @Override
  public void unsetRewriter() {
    enumUnboxerRewriter = null;
  }
}
