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

import static com.android.tools.r8.ir.optimize.info.OptimizationFeedback.getSimpleFeedback;
import static com.android.tools.r8.utils.MapUtils.ignoreKey;

import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.MethodResolutionResult.SingleResolutionResult;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.lens.GraphLens;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.conversion.MethodProcessor;
import com.android.tools.r8.ir.conversion.PostMethodProcessor;
import com.android.tools.r8.ir.optimize.Inliner.InlineAction;
import com.android.tools.r8.ir.optimize.Inliner.InlineResult;
import com.android.tools.r8.ir.optimize.Inliner.Reason;
import com.android.tools.r8.ir.optimize.inliner.FixedInliningReasonStrategy;
import com.android.tools.r8.ir.optimize.inliner.InliningIRProvider;
import com.android.tools.r8.ir.optimize.inliner.NopWhyAreYouNotInliningReporter;
import com.android.tools.r8.ir.optimize.inliner.multicallerinliner.MultiCallerInlinerCallGraph;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.IntBox;
import com.android.tools.r8.utils.LazyBox;
import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.utils.collections.LongLivedProgramMethodSetBuilder;
import com.android.tools.r8.utils.collections.ProgramMethodMap;
import com.android.tools.r8.utils.collections.ProgramMethodMultiset;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;

// TODO(b/142300882): If a method is selected for multi caller inlining, then if it is reprocessed
//  and we inline into it, we should potentially disable multi caller inlining for that method (or
//  we should disallow inlining into it).
public class MultiCallerInliner {

  private final AppView<AppInfoWithLiveness> appView;

  // Maps each method to the set of inlineable call sites targeting the method, or Optional.empty()
  // if we have stopped tracking the inlineable call sites.
  private final ProgramMethodMap<Optional<ProgramMethodMultiset>> multiInlineCallEdges =
      ProgramMethodMap.createConcurrent();

  private final int[] multiCallerInliningInstructionLimits;

  MultiCallerInliner(AppView<AppInfoWithLiveness> appView) {
    this.appView = appView;
    this.multiCallerInliningInstructionLimits =
        appView.options().inlinerOptions().multiCallerInliningInstructionLimits;
  }

  void recordCallEdgesForMultiCallerInlining(
      ProgramMethod method, IRCode code, MethodProcessor methodProcessor, Timing timing) {
    if (!methodProcessor.isPrimaryMethodProcessor()) {
      return;
    }

    timing.time(
        "Multi caller inliner: Record call edges",
        () -> recordCallEdgesForMultiCallerInlining(method, code, methodProcessor));
  }

  private void recordCallEdgesForMultiCallerInlining(
      ProgramMethod method, IRCode code, MethodProcessor methodProcessor) {
    LazyBox<DefaultInliningOracle> lazyOracle =
        new LazyBox<>(
            () -> {
              int inliningInstructionAllowance = Integer.MAX_VALUE;
              return new DefaultInliningOracle(
                  appView,
                  new FixedInliningReasonStrategy(Reason.MULTI_CALLER_CANDIDATE),
                  method,
                  methodProcessor,
                  inliningInstructionAllowance);
            });
    for (InvokeMethod invoke : code.<InvokeMethod>instructions(Instruction::isInvokeMethod)) {
      // Don't attempt to multi caller inline constructors. To determine if a constructor is
      // eligible for inlining, the inliner builds IR for the constructor, which we want to avoid
      // here for build speed.
      if (invoke.isInvokeConstructor(appView.dexItemFactory())) {
        continue;
      }

      SingleResolutionResult<?> resolutionResult =
          appView
              .appInfo()
              .resolveMethodLegacy(invoke.getInvokedMethod(), invoke.getInterfaceBit())
              .asSingleResolution();
      if (resolutionResult == null
          || resolutionResult.isAccessibleFrom(method, appView).isPossiblyFalse()) {
        continue;
      }

      ProgramMethod singleTarget = invoke.lookupSingleProgramTarget(appView, method);
      if (singleTarget == null
          || !methodProcessor.getCallSiteInformation().isMultiCallerInlineCandidate(singleTarget)) {
        continue;
      }

      InlineResult inlineResult =
          lazyOracle
              .computeIfAbsent()
              .computeInlining(
                  code,
                  invoke,
                  resolutionResult,
                  singleTarget,
                  method,
                  ClassInitializationAnalysis.trivial(),
                  InliningIRProvider.getThrowingInstance(),
                  NopWhyAreYouNotInliningReporter.getInstance());
      if (inlineResult == null || inlineResult.isRetryAction()) {
        stopTrackingCallSitesForMethod(singleTarget);
        continue;
      }

      InlineAction action = inlineResult.asInlineAction();
      assert action.reason == Reason.MULTI_CALLER_CANDIDATE;
      recordCallEdgeForMultiCallerInlining(method, singleTarget, methodProcessor);
    }
  }

  void recordCallEdgeForMultiCallerInlining(
      ProgramMethod method, ProgramMethod singleTarget, MethodProcessor methodProcessor) {
    Optional<ProgramMethodMultiset> value =
        multiInlineCallEdges.computeIfAbsent(
            singleTarget, ignoreKey(() -> Optional.of(ProgramMethodMultiset.createConcurrent())));

    // If we are not tracking the callers for the single target, then just return. In this case, we
    // have previously found that the single target is ineligible for multi caller inlining.
    if (!value.isPresent()) {
      return;
    }

    // Record that we have seen a call site that dispatched to the single target which is eligible
    // for inlining.
    ProgramMethodMultiset callers = value.get();
    callers.add(method);

    // We track up to n call sites, where n is the size of multiCallerInliningInstructionLimits.
    if (callers.size() > multiCallerInliningInstructionLimits.length) {
      stopTrackingCallSitesForMethodIfDefinitelyIneligibleForMultiCallerInlining(
          method, singleTarget, methodProcessor, callers);
    }
  }

  private void stopTrackingCallSitesForMethodIfDefinitelyIneligibleForMultiCallerInlining(
      ProgramMethod method,
      ProgramMethod singleTarget,
      MethodProcessor methodProcessor,
      ProgramMethodMultiset callers) {
    // First remove the call sites that no longer exist due to single caller inlining.
    callers.removeIf(caller -> caller.getOptimizationInfo().hasBeenInlinedIntoSingleCallSite());

    // Then compute the minimum number of call sites that are guaranteed to be present at the end
    // of the primary optimization pass.
    IntBox minimumCallers = new IntBox();
    callers.forEachEntry(
        (caller, calls) -> {
          // If these call sites are inside a method that has a single caller, then the call sites
          // could potentially disappear as a result of single caller inlining, so don't include
          // them.
          if (!methodProcessor.getCallSiteInformation().hasSingleCallSite(caller)) {
            minimumCallers.increment(calls);
          }
        });

    // If the threshold is definitely exceeded, then mark as ineligible for multi caller inlining.
    if (minimumCallers.get() > multiCallerInliningInstructionLimits.length) {
      stopTrackingCallSitesForMethod(singleTarget);
    }
  }

  private void stopTrackingCallSitesForMethod(ProgramMethod method) {
    multiInlineCallEdges.put(method, Optional.empty());
  }

  void onMethodPruned(ProgramMethod method) {
    assert !multiInlineCallEdges.containsKey(method);
  }

  public void onLastWaveDone(
      PostMethodProcessor.Builder postMethodProcessorBuilder,
      ExecutorService executorService,
      Timing timing)
      throws ExecutionException {
    timing.begin("Multi caller inliner");
    MultiCallerInlinerCallGraph callGraph =
        timing.time(
            "Call graph construction",
            () -> MultiCallerInlinerCallGraph.builder(appView).build(executorService));
    LongLivedProgramMethodSetBuilder<ProgramMethodSet> multiInlineCallers =
        timing.time("Needs inlining analysis", () -> computeMultiInlineCallerMethods(callGraph));
    postMethodProcessorBuilder
        .rewrittenWithLens(appView)
        .merge(multiInlineCallers);
    timing.end();
  }

  private LongLivedProgramMethodSetBuilder<ProgramMethodSet> computeMultiInlineCallerMethods(
      MultiCallerInlinerCallGraph callGraph) {
    // The multi inline callers are always rewritten up until the graph lens of the primary
    // optimization pass, so we can safely merge them into the methods to reprocess (which may be
    // rewritten with a newer graph lens).
    GraphLens currentGraphLens = appView.graphLens();
    LongLivedProgramMethodSetBuilder<ProgramMethodSet> multiInlineCallers =
        LongLivedProgramMethodSetBuilder.createForIdentitySet(currentGraphLens);
    multiInlineCallEdges.forEach(
        (singleTarget, value) -> {
          if (singleTarget.getDefinition().isLibraryMethodOverride().isPossiblyTrue()) {
            return;
          }

          if (!value.isPresent()) {
            return;
          }

          if (singleTarget.getDefinition().isInstance()
              && !appView.appInfo().isInstantiatedDirectlyOrIndirectly(singleTarget.getHolder())) {
            return;
          }

          ProgramMethodMultiset callers = value.get();
          callers.removeIf(
              method -> method.getOptimizationInfo().hasBeenInlinedIntoSingleCallSite());
          if (callers.size() == 0 || callers.size() > multiCallerInliningInstructionLimits.length) {
            return;
          }

          int numberOfCallSites = callGraph.getNode(singleTarget).getNumberOfCallSites();
          // TODO(b/142300882): The number of call sites according to the call graph should
          //  generally be >= the number of calls that the multi caller inliner has seen. This may
          //  not hold when calls are removed due to identical block prefix/suffix sharing, however.
          //  When this happens, the inliner may think that it can inline all call sites found in
          //  the call graph, although this may not actually be true.
          if (numberOfCallSites < callers.size()) {
            return;
          }
          if (callers.size() < numberOfCallSites) {
            // Can't inline all call sites.
            return;
          }

          int multiCallerInliningInstructionLimit =
              multiCallerInliningInstructionLimits[callers.size() - 1];
          if (!singleTarget
              .getDefinition()
              .getCode()
              .estimatedSizeForInliningAtMost(multiCallerInliningInstructionLimit)) {
            // Multi caller inlining could lead to a size increase according to the heuristic.
            return;
          }
          callers.forEachEntry(
              (caller, count) -> {
                if (!caller.getOptimizationInfo().hasBeenInlinedIntoSingleCallSite()) {
                  multiInlineCallers.add(caller, currentGraphLens);
                }
              });
          getSimpleFeedback().setMultiCallerMethod(singleTarget);
        });
    multiInlineCallEdges.clear();
    return multiInlineCallers;
  }
}
