//===--- Devirtualize.cpp - Helper for devirtualizing apply ---------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "sil-devirtualize-utility"
#include "swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h"
#include "swift/SILOptimizer/Utils/Devirtualize.h"
#include "swift/AST/Decl.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/SubstitutionMap.h"
#include "swift/AST/Types.h"
#include "swift/SIL/OptimizationRemark.h"
#include "swift/SIL/SILDeclRef.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILModule.h"
#include "swift/SIL/SILType.h"
#include "swift/SIL/SILValue.h"
#include "swift/SIL/InstructionUtils.h"
#include "swift/SILOptimizer/Utils/Local.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Casting.h"
using namespace swift;

STATISTIC(NumClassDevirt, "Number of class_method applies devirtualized");
STATISTIC(NumWitnessDevirt, "Number of witness_method applies devirtualized");

//===----------------------------------------------------------------------===//
//                         Class Method Optimization
//===----------------------------------------------------------------------===//

void swift::getAllSubclasses(ClassHierarchyAnalysis *CHA,
                             ClassDecl *CD,
                             CanType ClassType,
                             SILModule &M,
                             ClassHierarchyAnalysis::ClassList &Subs) {
  // Collect the direct and indirect subclasses for the class.
  // Sort these subclasses in the order they should be tested by the
  // speculative devirtualization. Different strategies could be used,
  // E.g. breadth-first, depth-first, etc.
  // Currently, let's use the breadth-first strategy.
  // The exact static type of the instance should be tested first.
  auto &DirectSubs = CHA->getDirectSubClasses(CD);
  auto &IndirectSubs = CHA->getIndirectSubClasses(CD);

  Subs.append(DirectSubs.begin(), DirectSubs.end());
  Subs.append(IndirectSubs.begin(), IndirectSubs.end());

  // FIXME: This is wrong -- we could have a non-generic class nested
  // inside a generic class
  if (isa<BoundGenericClassType>(ClassType)) {
    // Filter out any subclasses that do not inherit from this
    // specific bound class.
    auto RemovedIt = std::remove_if(Subs.begin(), Subs.end(),
        [&ClassType](ClassDecl *Sub){
          // FIXME: Add support for generic subclasses.
          if (Sub->isGenericContext())
            return false;
          auto SubCanTy = Sub->getDeclaredInterfaceType()->getCanonicalType();
          // Handle the usual case here: the class in question
          // should be a real subclass of a bound generic class.
          return !ClassType->isBindableToSuperclassOf(
              SubCanTy);
        });
    Subs.erase(RemovedIt, Subs.end());
  }
}

/// Returns true, if a method implementation corresponding to
/// the class_method applied to an instance of the class CD is
/// effectively final, i.e. it is statically known to be not overridden
/// by any subclasses of the class CD.
///
/// \p AI  invocation instruction
/// \p ClassType type of the instance
/// \p CD  static class of the instance whose method is being invoked
/// \p CHA class hierarchy analysis
static bool isEffectivelyFinalMethod(FullApplySite AI,
                                     CanType ClassType,
                                     ClassDecl *CD,
                                     ClassHierarchyAnalysis *CHA) {
  if (CD && CD->isFinal())
    return true;

  const DeclContext *DC = AI.getModule().getAssociatedContext();

  // Without an associated context we cannot perform any
  // access-based optimizations.
  if (!DC)
    return false;

  auto *CMI = cast<MethodInst>(AI.getCallee());

  if (!calleesAreStaticallyKnowable(AI.getModule(), CMI->getMember()))
    return false;

  auto *Method = CMI->getMember().getAbstractFunctionDecl();
  assert(Method && "Expected abstract function decl!");
  assert(!Method->isFinal() && "Unexpected indirect call to final method!");

  // If this method is not overridden in the module,
  // there is no other implementation.
  if (!Method->isOverridden())
    return true;

  // Class declaration may be nullptr, e.g. for cases like:
  // func foo<C:Base>(c: C) {}, where C is a class, but
  // it does not have a class decl.
  if (!CD)
    return false;

  if (!CHA)
    return false;

  // This is a private or a module internal class.
  //
  // We can analyze the class hierarchy rooted at it and
  // eventually devirtualize a method call more efficiently.

  ClassHierarchyAnalysis::ClassList Subs;
  getAllSubclasses(CHA, CD, ClassType, AI.getModule(), Subs);

  // This is the implementation of the method to be used
  // if the exact class of the instance would be CD.
  auto *ImplMethod = CD->findImplementingMethod(Method);

  // First, analyze all direct subclasses.
  for (auto S : Subs) {
    // Check if the subclass overrides a method and provides
    // a different implementation.
    auto *ImplFD = S->findImplementingMethod(Method);
    if (ImplFD != ImplMethod)
      return false;
  }

  return true;
}

/// Check if a given class is final in terms of a current
/// compilation, i.e.:
/// - it is really final
/// - or it is private and has not sub-classes
/// - or it is an internal class without sub-classes and
///   it is a whole-module compilation.
static bool isKnownFinalClass(ClassDecl *CD, SILModule &M,
                              ClassHierarchyAnalysis *CHA) {
  const DeclContext *DC = M.getAssociatedContext();

  if (CD->isFinal())
    return true;

  // Without an associated context we cannot perform any
  // access-based optimizations.
  if (!DC)
    return false;

  // Only handle classes defined within the SILModule's associated context.
  if (!CD->isChildContextOf(DC))
    return false;

  if (!CD->hasAccess())
    return false;

  // Only consider 'private' members, unless we are in whole-module compilation.
  switch (CD->getEffectiveAccess()) {
  case AccessLevel::Open:
    return false;
  case AccessLevel::Public:
  case AccessLevel::Internal:
    if (!M.isWholeModule())
      return false;
    break;
  case AccessLevel::FilePrivate:
  case AccessLevel::Private:
    break;
  }

  // Take the ClassHierarchyAnalysis into account.
  // If a given class has no subclasses and
  // - private
  // - or internal and it is a WMO compilation
  // then this class can be considered final for the purpose
  // of devirtualization.
  if (CHA) {
    if (!CHA->hasKnownDirectSubclasses(CD)) {
      switch (CD->getEffectiveAccess()) {
      case AccessLevel::Open:
        return false;
      case AccessLevel::Public:
      case AccessLevel::Internal:
        if (!M.isWholeModule())
          return false;
        break;
      case AccessLevel::FilePrivate:
      case AccessLevel::Private:
        break;
      }

      return true;
    }
  }

  return false;
}


// Attempt to get the instance for S, whose static type is the same as
// its exact dynamic type, returning a null SILValue() if we cannot find it.
// The information that a static type is the same as the exact dynamic,
// can be derived e.g.:
// - from a constructor or
// - from a successful outcome of a checked_cast_br [exact] instruction.
SILValue swift::getInstanceWithExactDynamicType(SILValue S,
                                                ClassHierarchyAnalysis *CHA) {
  auto *F = S->getFunction();
  auto &M = F->getModule();

  while (S) {
    S = stripCasts(S);

    if (isa<AllocRefInst>(S) || isa<MetatypeInst>(S)) {
      if (S->getType().getASTType()->hasDynamicSelfType())
        return SILValue();
      return S;
    }

    auto *Arg = dyn_cast<SILArgument>(S);
    if (!Arg)
      break;

    auto *SinglePred = Arg->getParent()->getSinglePredecessorBlock();
    if (!SinglePred) {
      if (!isa<SILFunctionArgument>(Arg))
        break;
      auto *CD = Arg->getType().getClassOrBoundGenericClass();
      // Check if this class is effectively final.
      if (!CD || !isKnownFinalClass(CD, M, CHA))
        break;
      return Arg;
    }

    // Traverse the chain of predecessors.
    if (isa<BranchInst>(SinglePred->getTerminator()) ||
        isa<CondBranchInst>(SinglePred->getTerminator())) {
      S = cast<SILPhiArgument>(Arg)->getIncomingPhiValue(SinglePred);
      continue;
    }

    // If it is a BB argument received on a success branch
    // of a checked_cast_br, then we know its exact type.
    auto *CCBI = dyn_cast<CheckedCastBranchInst>(SinglePred->getTerminator());
    if (!CCBI)
      break;
    if (!CCBI->isExact() || CCBI->getSuccessBB() != Arg->getParent())
      break;
    return S;
  }

  return SILValue();
}

/// Try to determine the exact dynamic type of an object.
/// returns the exact dynamic type of the object, or an empty type if the exact
/// type could not be determined.
SILType swift::getExactDynamicType(SILValue S,
                                   ClassHierarchyAnalysis *CHA,
                                   bool ForUnderlyingObject) {
  auto *F = S->getFunction();
  auto &M = F->getModule();

  // Set of values to be checked for their exact types.
  SmallVector<SILValue, 8> WorkList;
  // The detected type of the underlying object.
  SILType ResultType;
  // Set of processed values.
  llvm::SmallSet<SILValue, 8> Processed;
  WorkList.push_back(S);

  while (!WorkList.empty()) {
    auto V = WorkList.pop_back_val();
    if (!V)
      return SILType();
    if (Processed.count(V))
      continue;
    Processed.insert(V);
    // For underlying object strip casts and projections.
    // For the object itself, simply strip casts.
    V = ForUnderlyingObject ? getUnderlyingObject(V) : stripCasts(V);

    if (isa<AllocRefInst>(V) || isa<MetatypeInst>(V)) {
      if (ResultType && ResultType != V->getType())
        return SILType();
      ResultType = V->getType();
      continue;
    }

    if (isa<LiteralInst>(V)) {
      if (ResultType && ResultType != V->getType())
        return SILType();
      ResultType = V->getType();
      continue;
    }

    if (isa<StructInst>(V) || isa<TupleInst>(V) || isa<EnumInst>(V)) {
      if (ResultType && ResultType != V->getType())
        return SILType();
      ResultType = V->getType();
      continue;
    }

    if (ForUnderlyingObject) {
      if (isa<AllocationInst>(V)) {
        if (ResultType && ResultType != V->getType())
          return SILType();
        ResultType = V->getType();
        continue;
      }
    }

    auto Arg = dyn_cast<SILArgument>(V);
    if (!Arg) {
      // We don't know what it is.
      return SILType();
    }

    if (auto *FArg = dyn_cast<SILFunctionArgument>(Arg)) {
      // Bail on metatypes for now.
      if (FArg->getType().is<AnyMetatypeType>()) {
        return SILType();
      }
      auto *CD = FArg->getType().getClassOrBoundGenericClass();
      // If it is not class and it is a trivial type, then it
      // should be the exact type.
      if (!CD && FArg->getType().isTrivial(*F)) {
        if (ResultType && ResultType != FArg->getType())
          return SILType();
        ResultType = FArg->getType();
        continue;
      }

      if (!CD) {
        // It is not a class or a trivial type, so we don't know what it is.
        return SILType();
      }

      // Check if this class is effectively final.
      if (!isKnownFinalClass(CD, M, CHA)) {
        return SILType();
      }

      if (ResultType && ResultType != FArg->getType())
        return SILType();
      ResultType = FArg->getType();
      continue;
    }

    auto *SinglePred = Arg->getParent()->getSinglePredecessorBlock();
    if (SinglePred) {
      // If it is a BB argument received on a success branch
      // of a checked_cast_br, then we know its exact type.
      auto *CCBI = dyn_cast<CheckedCastBranchInst>(SinglePred->getTerminator());
      if (CCBI && CCBI->isExact() && CCBI->getSuccessBB() == Arg->getParent()) {
        if (ResultType && ResultType != Arg->getType())
          return SILType();
        ResultType = Arg->getType();
        continue;
      }
    }

    // It is a BB argument, look through incoming values. If they all have the
    // same exact type, then we consider it to be the type of the BB argument.
    SmallVector<SILValue, 4> IncomingValues;
    if (Arg->getSingleTerminatorOperands(IncomingValues)) {
      for (auto InValue : IncomingValues) {
        WorkList.push_back(InValue);
      }
      continue;
    }

    // The exact type is unknown.
    return SILType();
  }

  return ResultType;
}


/// Try to determine the exact dynamic type of the underlying object.
/// returns the exact dynamic type of a value, or an empty type if the exact
/// type could not be determined.
SILType
swift::getExactDynamicTypeOfUnderlyingObject(SILValue S,
                                             ClassHierarchyAnalysis *CHA) {
  return getExactDynamicType(S, CHA, /* ForUnderlyingObject */ true);
}

// Start with the substitutions from the apply.
// Try to propagate them to find out the real substitutions required
// to invoke the method.
static SubstitutionMap
getSubstitutionsForCallee(SILModule &M,
                          CanSILFunctionType baseCalleeType,
                          CanType derivedSelfType,
                          FullApplySite AI) {

  // If the base method is not polymorphic, no substitutions are required,
  // even if we originally had substitutions for calling the derived method.
  if (!baseCalleeType->isPolymorphic())
    return SubstitutionMap();

  // Add any generic substitutions for the base class.
  Type baseSelfType = baseCalleeType->getSelfParameter().getType();
  if (auto metatypeType = baseSelfType->getAs<MetatypeType>())
    baseSelfType = metatypeType->getInstanceType();

  auto *baseClassDecl = baseSelfType->getClassOrBoundGenericClass();
  assert(baseClassDecl && "not a class method");

  unsigned baseDepth = 0;
  SubstitutionMap baseSubMap;
  if (auto baseClassSig = baseClassDecl->getGenericSignatureOfContext()) {
    baseDepth = baseClassSig->getGenericParams().back()->getDepth() + 1;

    // Compute the type of the base class, starting from the
    // derived class type and the type of the method's self
    // parameter.
    Type derivedClass = derivedSelfType;
    if (auto metatypeType = derivedClass->getAs<MetatypeType>())
      derivedClass = metatypeType->getInstanceType();
    baseSubMap = derivedClass->getContextSubstitutionMap(
        M.getSwiftModule(), baseClassDecl);
  }

  SubstitutionMap origSubMap = AI.getSubstitutionMap();

  Type calleeSelfType = AI.getOrigCalleeType()->getSelfParameter().getType();
  if (auto metatypeType = calleeSelfType->getAs<MetatypeType>())
    calleeSelfType = metatypeType->getInstanceType();
  auto *calleeClassDecl = calleeSelfType->getClassOrBoundGenericClass();
  assert(calleeClassDecl && "self is not a class type");

  // Add generic parameters from the method itself, ignoring any generic
  // parameters from the derived class.
  unsigned origDepth = 0;
  if (auto calleeClassSig = calleeClassDecl->getGenericSignatureOfContext())
    origDepth = calleeClassSig->getGenericParams().back()->getDepth() + 1;

  auto baseCalleeSig = baseCalleeType->getGenericSignature();

  return
    SubstitutionMap::combineSubstitutionMaps(baseSubMap,
                                             origSubMap,
                                             CombineSubstitutionMaps::AtDepth,
                                             baseDepth,
                                             origDepth,
                                             baseCalleeSig);
}

static ApplyInst *replaceApplyInst(SILBuilder &B, SILLocation Loc,
                                   ApplyInst *OldAI,
                                   SILValue NewFn,
                                   SubstitutionMap NewSubs,
                                   ArrayRef<SILValue> NewArgs,
                                   ArrayRef<SILValue> NewArgBorrows) {
  auto *NewAI = B.createApply(Loc, NewFn, NewSubs, NewArgs,
                              OldAI->isNonThrowing());

  if (!NewArgBorrows.empty()) {
    for (SILValue Arg : NewArgBorrows) {
      B.createEndBorrow(Loc, Arg);
    }
  }

  // Check if any casting is required for the return value.
  SILValue ResultValue =
    castValueToABICompatibleType(&B, Loc, NewAI, NewAI->getType(),
                                 OldAI->getType());

  OldAI->replaceAllUsesWith(ResultValue);
  return NewAI;
}

static TryApplyInst *replaceTryApplyInst(SILBuilder &B, SILLocation Loc,
                                         TryApplyInst *OldTAI, SILValue NewFn,
                                         SubstitutionMap NewSubs,
                                         ArrayRef<SILValue> NewArgs,
                                         SILFunctionConventions Conv,
                                         ArrayRef<SILValue> NewArgBorrows) {
  SILBasicBlock *NormalBB = OldTAI->getNormalBB();
  SILBasicBlock *ResultBB = nullptr;

  SILType NewResultTy = Conv.getSILResultType();

  // Does the result value need to be casted?
  auto OldResultTy = NormalBB->getArgument(0)->getType();
  bool ResultCastRequired = NewResultTy != OldResultTy;

  // Create a new normal BB only if the result of the new apply differs
  // in type from the argument of the original normal BB.
  if (!ResultCastRequired) {
    ResultBB = NormalBB;
  } else {
    ResultBB = B.getFunction().createBasicBlockBefore(NormalBB);
    ResultBB->createPhiArgument(NewResultTy, ValueOwnershipKind::Owned);
  }

  // We can always just use the original error BB because we'll be
  // deleting the edge to it from the old TAI.
  SILBasicBlock *ErrorBB = OldTAI->getErrorBB();

  // Insert a try_apply here.
  // Note that this makes this block temporarily double-terminated!
  // We won't fix that until deleteDevirtualizedApply.
  auto NewTAI = B.createTryApply(Loc, NewFn, NewSubs, NewArgs,
                                 ResultBB, ErrorBB);

  if (!NewArgBorrows.empty()) {
    B.setInsertionPoint(NormalBB->begin());
    for (SILValue Arg : NewArgBorrows) {
      B.createEndBorrow(Loc, Arg);
    }
    B.setInsertionPoint(ErrorBB->begin());
    for (SILValue Arg : NewArgBorrows) {
      B.createEndBorrow(Loc, Arg);
    }
  }

  if (ResultCastRequired) {
    B.setInsertionPoint(ResultBB);

    SILValue ResultValue = ResultBB->getArgument(0);
    ResultValue = castValueToABICompatibleType(&B, Loc, ResultValue,
                                               NewResultTy, OldResultTy);
    B.createBranch(Loc, NormalBB, { ResultValue });
  }

  B.setInsertionPoint(NormalBB->begin());
  return NewTAI;
}

static BeginApplyInst *replaceBeginApplyInst(SILBuilder &B, SILLocation Loc,
                                             BeginApplyInst *OldBAI,
                                             SILValue NewFn,
                                             SubstitutionMap NewSubs,
                                             ArrayRef<SILValue> NewArgs,
                                             ArrayRef<SILValue> NewArgBorrows) {
  auto *NewBAI =
      B.createBeginApply(Loc, NewFn, NewSubs, NewArgs, OldBAI->isNonThrowing());

  // Forward the token.
  OldBAI->getTokenResult()->replaceAllUsesWith(NewBAI->getTokenResult());

  auto OldYields = OldBAI->getYieldedValues();
  auto NewYields = NewBAI->getYieldedValues();
  assert(OldYields.size() == NewYields.size());

  for (auto i : indices(OldYields)) {
    auto OldYield = OldYields[i];
    auto NewYield = NewYields[i];
    NewYield = castValueToABICompatibleType(&B, Loc, NewYield,
                                            NewYield->getType(),
                                            OldYield->getType());
    OldYield->replaceAllUsesWith(NewYield);
  }

  if (NewArgBorrows.empty())
    return NewBAI;

  SILValue token = NewBAI->getTokenResult();

  // The token will only be used by end_apply and abort_apply. Use that to
  // insert the end_borrows we need.
  for (auto *use : token->getUses()) {
    SILBuilderWithScope builder(use->getUser(), B.getBuilderContext());
    for (SILValue borrow : NewArgBorrows) {
      builder.createEndBorrow(Loc, borrow);
    }
  }

  return NewBAI;
}

static PartialApplyInst *replacePartialApplyInst(SILBuilder &B, SILLocation Loc,
                                                 PartialApplyInst *OldPAI,
                                                 SILValue NewFn,
                                                 SubstitutionMap NewSubs,
                                                 ArrayRef<SILValue> NewArgs) {
  auto Convention =
    OldPAI->getType().getAs<SILFunctionType>()->getCalleeConvention();
  auto *NewPAI = B.createPartialApply(Loc, NewFn, NewSubs, NewArgs,
                                      Convention);

  // Check if any casting is required for the partially-applied function.
  SILValue ResultValue = castValueToABICompatibleType(
      &B, Loc, NewPAI, NewPAI->getType(), OldPAI->getType());
  OldPAI->replaceAllUsesWith(ResultValue);

  return NewPAI;
}

static ApplySite replaceApplySite(SILBuilder &B, SILLocation Loc,
                                  ApplySite OldAS, SILValue NewFn,
                                  SubstitutionMap NewSubs,
                                  ArrayRef<SILValue> NewArgs,
                                  SILFunctionConventions Conv,
                                  ArrayRef<SILValue> NewArgBorrows) {
  switch (OldAS.getKind()) {
  case ApplySiteKind::ApplyInst: {
    auto *OldAI = cast<ApplyInst>(OldAS);
    return replaceApplyInst(B, Loc, OldAI, NewFn, NewSubs, NewArgs, NewArgBorrows);
  }
  case ApplySiteKind::TryApplyInst: {
    auto *OldTAI = cast<TryApplyInst>(OldAS);
    return replaceTryApplyInst(B, Loc, OldTAI, NewFn, NewSubs, NewArgs, Conv,
                               NewArgBorrows);
  }
  case ApplySiteKind::BeginApplyInst: {
    auto *OldBAI = dyn_cast<BeginApplyInst>(OldAS);
    return replaceBeginApplyInst(B, Loc, OldBAI, NewFn, NewSubs, NewArgs,
                                 NewArgBorrows);
  }
  case ApplySiteKind::PartialApplyInst: {
    assert(NewArgBorrows.empty());
    auto *OldPAI = cast<PartialApplyInst>(OldAS);
    return replacePartialApplyInst(B, Loc, OldPAI, NewFn, NewSubs, NewArgs);
  }
  }
}

/// Delete an apply site that's been successfully devirtualized.
void swift::deleteDevirtualizedApply(ApplySite Old) {
  auto *OldApply = Old.getInstruction();
  recursivelyDeleteTriviallyDeadInstructions(OldApply, true);
}

SILFunction *swift::getTargetClassMethod(SILModule &M,
                                         ClassDecl *CD,
                                         MethodInst *MI) {
  assert((isa<ClassMethodInst>(MI) || isa<SuperMethodInst>(MI)) &&
         "Only class_method and super_method instructions are supported");

  SILDeclRef Member = MI->getMember();
  return M.lookUpFunctionInVTable(CD, Member);
}

CanType swift::getSelfInstanceType(CanType ClassOrMetatypeType) {
  if (auto MetaType = dyn_cast<MetatypeType>(ClassOrMetatypeType))
    ClassOrMetatypeType = MetaType.getInstanceType();

  if (auto SelfType = dyn_cast<DynamicSelfType>(ClassOrMetatypeType))
    ClassOrMetatypeType = SelfType.getSelfType();
  
  return ClassOrMetatypeType;
}

/// Check if it is possible to devirtualize an Apply instruction
/// and a class member obtained using the class_method instruction into
/// a direct call to a specific member of a specific class.
///
/// \p AI is the apply to devirtualize.
/// \p CD is the class declaration we are devirtualizing for.
/// return true if it is possible to devirtualize, false - otherwise.
bool swift::canDevirtualizeClassMethod(FullApplySite AI,
                                       ClassDecl *CD,
                                       OptRemark::Emitter *ORE,
                                       bool isEffectivelyFinalMethod) {

  LLVM_DEBUG(llvm::dbgs() << "    Trying to devirtualize : "
                          << *AI.getInstruction());

  SILModule &Mod = AI.getModule();

  auto *MI = cast<MethodInst>(AI.getCallee());

  // Find the implementation of the member which should be invoked.
  auto *F = getTargetClassMethod(Mod, CD, MI);

  // If we do not find any such function, we have no function to devirtualize
  // to... so bail.
  if (!F) {
    LLVM_DEBUG(llvm::dbgs() << "        FAIL: Could not find matching VTable "
                               "or vtable method for this class.\n");
    return false;
  }

  // We need to disable the  “effectively final” opt if a function is inlinable
  if (isEffectivelyFinalMethod && AI.getFunction()->isSerialized()) {
    LLVM_DEBUG(llvm::dbgs() << "        FAIL: Could not optimize function "
                               "because it is an effectively-final inlinable: "
                            << AI.getFunction()->getName() << "\n");
    return false;
  }

  // Mandatory inlining does class method devirtualization. I'm not sure if this
  // is really needed, but some test rely on this.
  // So even for Onone functions we have to do it if the SILStage is raw.
  if (F->getModule().getStage() != SILStage::Raw && !F->shouldOptimize()) {
    // Do not consider functions that should not be optimized.
    LLVM_DEBUG(llvm::dbgs() << "        FAIL: Could not optimize function "
                            << " because it is marked no-opt: " << F->getName()
                            << "\n");
    return false;
  }

  if (AI.getFunction()->isSerialized()) {
    // function_ref inside fragile function cannot reference a private or
    // hidden symbol.
    if (!F->hasValidLinkageForFragileRef())
      return false;
  }

  // devirtualizeClassMethod below does not support this case. It currently
  // assumes it can try_apply call the target.
  if (!F->getLoweredFunctionType()->hasErrorResult() &&
      isa<TryApplyInst>(AI.getInstruction())) {
    LLVM_DEBUG(llvm::dbgs() << "        FAIL: Trying to devirtualize a "
          "try_apply but vtable entry has no error result.\n");
    return false;
  }

  return true;
}

/// Devirtualize an apply of a class method.
///
/// \p AI is the apply to devirtualize.
/// \p ClassOrMetatype is a class value or metatype value that is the
///    self argument of the apply we will devirtualize.
/// return the result value of the new ApplyInst if created one or null.
FullApplySite swift::devirtualizeClassMethod(FullApplySite AI,
                                             SILValue ClassOrMetatype,
                                             ClassDecl *CD,
                                             OptRemark::Emitter *ORE) {
  LLVM_DEBUG(llvm::dbgs() << "    Trying to devirtualize : "
                          << *AI.getInstruction());

  SILModule &Mod = AI.getModule();
  auto *MI = cast<MethodInst>(AI.getCallee());

  auto *F = getTargetClassMethod(Mod, CD, MI);

  CanSILFunctionType GenCalleeType = F->getLoweredFunctionType();

  SubstitutionMap Subs =
    getSubstitutionsForCallee(Mod, GenCalleeType,
                              ClassOrMetatype->getType().getASTType(),
                              AI);
  CanSILFunctionType SubstCalleeType = GenCalleeType;
  if (GenCalleeType->isPolymorphic())
    SubstCalleeType = GenCalleeType->substGenericArgs(Mod, Subs);
  SILFunctionConventions substConv(SubstCalleeType, Mod);

  SILBuilderWithScope B(AI.getInstruction());
  SILLocation Loc = AI.getLoc();
  auto *FRI = B.createFunctionRefFor(Loc, F);

  // Create the argument list for the new apply, casting when needed
  // in order to handle covariant indirect return types and
  // contravariant argument types.
  SmallVector<SILValue, 8> NewArgs;

  // If we have a value that is owned, but that we are going to use in as a
  // guaranteed argument, we need to borrow/unborrow the argument. Otherwise, we
  // will introduce new consuming uses. In contrast, if we have an owned value,
  // we are ok due to the forwarding nature of upcasts.
  SmallVector<SILValue, 8> NewArgBorrows;

  auto IndirectResultArgIter = AI.getIndirectSILResults().begin();
  for (auto ResultTy : substConv.getIndirectSILResultTypes()) {
    NewArgs.push_back(
        castValueToABICompatibleType(&B, Loc, *IndirectResultArgIter,
                                     IndirectResultArgIter->getType(), ResultTy));
    ++IndirectResultArgIter;
  }

  auto ParamArgIter = AI.getArgumentsWithoutIndirectResults().begin();
  // Skip the last parameter, which is `self`. Add it below.
  for (auto param : substConv.getParameters()) {
    auto paramType = substConv.getSILType(param);
    SILValue arg = *ParamArgIter;
    if (B.hasOwnership()
        && arg->getType().isObject()
        && arg.getOwnershipKind() == ValueOwnershipKind::Owned
        && param.isGuaranteed()) {
      SILBuilderWithScope builder(AI.getInstruction(), B);
      arg = builder.createBeginBorrow(Loc, arg);
      NewArgBorrows.push_back(arg);
    }
    arg = castValueToABICompatibleType(&B, Loc, arg, ParamArgIter->getType(),
                                       paramType);
    NewArgs.push_back(arg);
    ++ParamArgIter;
  }
  ApplySite NewAS = replaceApplySite(B, Loc, AI, FRI, Subs, NewArgs, substConv,
                                     NewArgBorrows);
  FullApplySite NewAI = FullApplySite::isa(NewAS.getInstruction());
  assert(NewAI);

  LLVM_DEBUG(llvm::dbgs() << "        SUCCESS: " << F->getName() << "\n");
  if (ORE)
    ORE->emit([&]() {
        using namespace OptRemark;
        return RemarkPassed("ClassMethodDevirtualized", *AI.getInstruction())
               << "Devirtualized call to class method " << NV("Method", F);
      });
  NumClassDevirt++;

  return NewAI;
}

FullApplySite
swift::tryDevirtualizeClassMethod(FullApplySite AI, SILValue ClassInstance,
                                  ClassDecl *CD,
                                  OptRemark::Emitter *ORE,
                                  bool isEffectivelyFinalMethod) {
  if (!canDevirtualizeClassMethod(AI, CD, ORE, isEffectivelyFinalMethod))
    return FullApplySite();
  return devirtualizeClassMethod(AI, ClassInstance, CD, ORE);
}


//===----------------------------------------------------------------------===//
//                        Witness Method Optimization
//===----------------------------------------------------------------------===//

/// Compute substitutions for making a direct call to a SIL function with
/// @convention(witness_method) convention.
///
/// Such functions have a substituted generic signature where the
/// abstract `Self` parameter from the original type of the protocol
/// requirement is replaced by a concrete type.
///
/// Thus, the original substitutions of the apply instruction that
/// are written in terms of the requirement's generic signature need
/// to be remapped to substitutions suitable for the witness signature.
///
/// Supported remappings are:
///
/// - (Concrete witness thunk) Original substitutions:
///   [Self := ConcreteType, R0 := X0, R1 := X1, ...]
/// - Requirement generic signature:
///   <Self : P, R0, R1, ...>
/// - Witness thunk generic signature:
///   <W0, W1, ...>
/// - Remapped substitutions:
///   [W0 := X0, W1 := X1, ...]
///
/// - (Class witness thunk) Original substitutions:
///   [Self := C<A0, A1>, T0 := X0, T1 := X1, ...]
/// - Requirement generic signature:
///   <Self : P, R0, R1, ...>
/// - Witness thunk generic signature:
///   <Self : C<B0, B1>, B0, B1, W0, W1, ...>
/// - Remapped substitutions:
///   [Self := C<B0, B1>, B0 := A0, B1 := A1, W0 := X0, W1 := X1]
///
/// - (Default witness thunk) Original substitutions:
///   [Self := ConcreteType, R0 := X0, R1 := X1, ...]
/// - Requirement generic signature:
///   <Self : P, R0, R1, ...>
/// - Witness thunk generic signature:
///   <Self : P, W0, W1, ...>
/// - Remapped substitutions:
///   [Self := ConcreteType, W0 := X0, W1 := X1, ...]
///
/// \param conformanceRef The (possibly-specialized) conformance
/// \param requirementSig The generic signature of the requirement
/// \param witnessThunkSig The generic signature of the witness method
/// \param origSubMap The substitutions from the call instruction
/// \param isSelfAbstract True if the Self type of the witness method is
/// still abstract (i.e., not a concrete type).
/// \param classWitness The ClassDecl if this is a class witness method
static SubstitutionMap
getWitnessMethodSubstitutions(
    ModuleDecl *mod,
    ProtocolConformanceRef conformanceRef,
    GenericSignature *requirementSig,
    GenericSignature *witnessThunkSig,
    SubstitutionMap origSubMap,
    bool isSelfAbstract,
    ClassDecl *classWitness) {

  if (witnessThunkSig == nullptr)
    return SubstitutionMap();

  if (isSelfAbstract && !classWitness)
    return origSubMap;

  assert(!conformanceRef.isAbstract());
  auto conformance = conformanceRef.getConcrete();

  // If `Self` maps to a bound generic type, this gives us the
  // substitutions for the concrete type's generic parameters.
  auto baseSubMap = conformance->getSubstitutions(mod);

  unsigned baseDepth = 0;
  auto *rootConformance = conformance->getRootNormalConformance();
  if (auto *witnessSig = rootConformance->getGenericSignature())
    baseDepth = witnessSig->getGenericParams().back()->getDepth() + 1;

  // If the witness has a class-constrained 'Self' generic parameter,
  // we have to build a new substitution map that shifts all generic
  // parameters down by one.
  if (classWitness != nullptr) {
    auto *proto = conformance->getProtocol();
    auto selfType = proto->getSelfInterfaceType();

    auto selfSubMap = SubstitutionMap::getProtocolSubstitutions(
        proto, selfType.subst(origSubMap), conformanceRef);
    if (baseSubMap.empty()) {
      assert(baseDepth == 0);
      baseSubMap = selfSubMap;
    } else {
      baseSubMap = SubstitutionMap::combineSubstitutionMaps(
          selfSubMap,
          baseSubMap,
          CombineSubstitutionMaps::AtDepth,
          /*firstDepth=*/1,
          /*secondDepth=*/0,
          witnessThunkSig);
    }
    baseDepth += 1;
  }

  return SubstitutionMap::combineSubstitutionMaps(
      baseSubMap,
      origSubMap,
      CombineSubstitutionMaps::AtDepth,
      /*firstDepth=*/baseDepth,
      /*secondDepth=*/1,
      witnessThunkSig);
}

SubstitutionMap
swift::getWitnessMethodSubstitutions(SILModule &Module, ApplySite AI,
                                     SILFunction *F,
                                     ProtocolConformanceRef CRef) {
  auto witnessFnTy = F->getLoweredFunctionType();
  assert(witnessFnTy->getRepresentation() ==
         SILFunctionTypeRepresentation::WitnessMethod);

  auto requirementSig = AI.getOrigCalleeType()->getGenericSignature();
  auto witnessThunkSig = witnessFnTy->getGenericSignature();

  SubstitutionMap origSubs = AI.getSubstitutionMap();

  auto *mod = Module.getSwiftModule();
  bool isSelfAbstract =
    witnessFnTy->getSelfInstanceType()->is<GenericTypeParamType>();
  auto *classWitness = witnessFnTy->getWitnessMethodClass();

  return ::getWitnessMethodSubstitutions(mod, CRef, requirementSig,
                                         witnessThunkSig, origSubs,
                                         isSelfAbstract, classWitness);
}

/// Generate a new apply of a function_ref to replace an apply of a
/// witness_method when we've determined the actual function we'll end
/// up calling.
static ApplySite
devirtualizeWitnessMethod(ApplySite AI, SILFunction *F,
                          ProtocolConformanceRef C, OptRemark::Emitter *ORE) {
  // We know the witness thunk and the corresponding set of substitutions
  // required to invoke the protocol method at this point.
  auto &Module = AI.getModule();

  // Collect all the required substitutions.
  //
  // The complete set of substitutions may be different, e.g. because the found
  // witness thunk F may have been created by a specialization pass and have
  // additional generic parameters.
  auto SubMap = getWitnessMethodSubstitutions(Module, AI, F, C);

  // Figure out the exact bound type of the function to be called by
  // applying all substitutions.
  auto CalleeCanType = F->getLoweredFunctionType();
  auto SubstCalleeCanType = CalleeCanType->substGenericArgs(Module, SubMap);

  // Collect arguments from the apply instruction.
  SmallVector<SILValue, 4> Arguments;
  SmallVector<SILValue, 4> BorrowedArgs;

  // Iterate over the non self arguments and add them to the
  // new argument list, upcasting when required.
  SILBuilderWithScope B(AI.getInstruction());
  SILFunctionConventions substConv(SubstCalleeCanType, Module);
  unsigned substArgIdx = AI.getCalleeArgIndexOfFirstAppliedArg();
  for (auto arg : AI.getArguments()) {
    auto paramInfo = substConv.getSILArgumentConvention(substArgIdx);
    auto paramType = substConv.getSILArgumentType(substArgIdx++);
    if (arg->getType() != paramType) {
      if (B.hasOwnership()
          && AI.getKind() != ApplySiteKind::PartialApplyInst
          && arg->getType().isObject()
          && arg.getOwnershipKind() == ValueOwnershipKind::Owned
          && paramInfo.isGuaranteedConvention()) {
        SILBuilderWithScope builder(AI.getInstruction(), B);
        arg = builder.createBeginBorrow(AI.getLoc(), arg);
        BorrowedArgs.push_back(arg);
      }
      arg = castValueToABICompatibleType(&B, AI.getLoc(), arg,
                                         arg->getType(), paramType);
    }
    Arguments.push_back(arg);
  }
  assert(substArgIdx == substConv.getNumSILArguments());

  // Replace old apply instruction by a new apply instruction that invokes
  // the witness thunk.
  SILBuilderWithScope Builder(AI.getInstruction());
  SILLocation Loc = AI.getLoc();
  auto *FRI = Builder.createFunctionRefFor(Loc, F);

  ApplySite SAI = replaceApplySite(Builder, Loc, AI, FRI, SubMap, Arguments,
                                   substConv, BorrowedArgs);

  if (ORE)
    ORE->emit([&]() {
        using namespace OptRemark;
        return RemarkPassed("WitnessMethodDevirtualized", *AI.getInstruction())
               << "Devirtualized call to " << NV("Method", F);
      });
  NumWitnessDevirt++;
  return SAI;
}

static bool canDevirtualizeWitnessMethod(ApplySite AI) {
  SILFunction *F;
  SILWitnessTable *WT;

  auto *WMI = cast<WitnessMethodInst>(AI.getCallee());

  std::tie(F, WT) =
    AI.getModule().lookUpFunctionInWitnessTable(WMI->getConformance(),
                                                WMI->getMember());

  if (!F)
    return false;

  if (AI.getFunction()->isSerialized()) {
    // function_ref inside fragile function cannot reference a private or
    // hidden symbol.
    if (!F->hasValidLinkageForFragileRef())
      return false;
  }

  // devirtualizeWitnessMethod below does not support this case. It currently
  // assumes it can try_apply call the target.
  if (!F->getLoweredFunctionType()->hasErrorResult() &&
      isa<TryApplyInst>(AI.getInstruction())) {
    LLVM_DEBUG(llvm::dbgs() << "        FAIL: Trying to devirtualize a "
          "try_apply but wtable entry has no error result.\n");
    return false;
  }

  return true;
}

/// In the cases where we can statically determine the function that
/// we'll call to, replace an apply of a witness_method with an apply
/// of a function_ref, returning the new apply.
ApplySite
swift::tryDevirtualizeWitnessMethod(ApplySite AI, OptRemark::Emitter *ORE) {
  if (!canDevirtualizeWitnessMethod(AI))
    return ApplySite();

  SILFunction *F;
  SILWitnessTable *WT;

  auto *WMI = cast<WitnessMethodInst>(AI.getCallee());

  std::tie(F, WT) =
    AI.getModule().lookUpFunctionInWitnessTable(WMI->getConformance(),
                                                WMI->getMember());

  return devirtualizeWitnessMethod(AI, F, WMI->getConformance(), ORE);
}

//===----------------------------------------------------------------------===//
//                              Top Level Driver
//===----------------------------------------------------------------------===//

/// Attempt to devirtualize the given apply if possible, and return a
/// new instruction in that case, or nullptr otherwise.
ApplySite swift::tryDevirtualizeApply(ApplySite AI,
                                      ClassHierarchyAnalysis *CHA,
                                      OptRemark::Emitter *ORE) {
  LLVM_DEBUG(llvm::dbgs() << "    Trying to devirtualize: "
                          << *AI.getInstruction());

  // Devirtualize apply instructions that call witness_method instructions:
  //
  //   %8 = witness_method $Optional<UInt16>, #LogicValue.boolValue!getter.1
  //   %9 = apply %8<Self = CodeUnit?>(%6#1) : ...
  //
  if (isa<WitnessMethodInst>(AI.getCallee()))
    return tryDevirtualizeWitnessMethod(AI, ORE);

  // TODO: check if we can also de-virtualize partial applies of class methods.
  FullApplySite FAS = FullApplySite::isa(AI.getInstruction());
  if (!FAS)
    return ApplySite();

  /// Optimize a class_method and alloc_ref pair into a direct function
  /// reference:
  ///
  /// \code
  /// %XX = alloc_ref $Foo
  /// %YY = class_method %XX : $Foo, #Foo.get!1 : $@convention(method)...
  /// \endcode
  ///
  ///  or
  ///
  /// %XX = metatype $...
  /// %YY = class_method %XX : ...
  ///
  ///  into
  ///
  /// %YY = function_ref @...
  if (auto *CMI = dyn_cast<ClassMethodInst>(FAS.getCallee())) {
    auto Instance = stripUpCasts(CMI->getOperand());
    auto ClassType = getSelfInstanceType(Instance->getType().getASTType());
    auto *CD = ClassType.getClassOrBoundGenericClass();

    if (isEffectivelyFinalMethod(FAS, ClassType, CD, CHA))
      return tryDevirtualizeClassMethod(FAS, Instance, CD, ORE,
                                        true /*isEffectivelyFinalMethod*/);

    // Try to check if the exact dynamic type of the instance is statically
    // known.
    if (auto Instance = getInstanceWithExactDynamicType(CMI->getOperand(), CHA))
      return tryDevirtualizeClassMethod(FAS, Instance, CD, ORE);

    if (auto ExactTy = getExactDynamicType(CMI->getOperand(), CHA)) {
      if (ExactTy == CMI->getOperand()->getType())
        return tryDevirtualizeClassMethod(FAS, CMI->getOperand(), CD, ORE);
    }
  }

  if (isa<SuperMethodInst>(FAS.getCallee())) {
    auto Instance = FAS.getArguments().back();
    auto ClassType = getSelfInstanceType(Instance->getType().getASTType());
    auto *CD = ClassType.getClassOrBoundGenericClass();

    return tryDevirtualizeClassMethod(FAS, Instance, CD, ORE);
  }

  return ApplySite();
}

bool swift::canDevirtualizeApply(FullApplySite AI, ClassHierarchyAnalysis *CHA) {
  LLVM_DEBUG(llvm::dbgs() << "    Trying to devirtualize: "
                          << *AI.getInstruction());

  // Devirtualize apply instructions that call witness_method instructions:
  //
  //   %8 = witness_method $Optional<UInt16>, #LogicValue.boolValue!getter.1
  //   %9 = apply %8<Self = CodeUnit?>(%6#1) : ...
  //
  if (isa<WitnessMethodInst>(AI.getCallee()))
    return canDevirtualizeWitnessMethod(AI);

  /// Optimize a class_method and alloc_ref pair into a direct function
  /// reference:
  ///
  /// \code
  /// %XX = alloc_ref $Foo
  /// %YY = class_method %XX : $Foo, #Foo.get!1 : $@convention(method)...
  /// \endcode
  ///
  ///  or
  ///
  /// %XX = metatype $...
  /// %YY = class_method %XX : ...
  ///
  ///  into
  ///
  /// %YY = function_ref @...
  if (auto *CMI = dyn_cast<ClassMethodInst>(AI.getCallee())) {
    auto Instance = stripUpCasts(CMI->getOperand());
    auto ClassType = getSelfInstanceType(Instance->getType().getASTType());
    auto *CD = ClassType.getClassOrBoundGenericClass();

    if (isEffectivelyFinalMethod(AI, ClassType, CD, CHA))
      return canDevirtualizeClassMethod(AI, CD,
                                        nullptr /*ORE*/,
                                        true /*isEffectivelyFinalMethod*/);

    // Try to check if the exact dynamic type of the instance is statically
    // known.
    if (auto Instance = getInstanceWithExactDynamicType(CMI->getOperand(), CHA))
      return canDevirtualizeClassMethod(AI, CD);

    if (auto ExactTy = getExactDynamicType(CMI->getOperand(), CHA)) {
      if (ExactTy == CMI->getOperand()->getType())
        return canDevirtualizeClassMethod(AI, CD);
    }
  }

  if (isa<SuperMethodInst>(AI.getCallee())) {
    auto Instance = AI.getArguments().back();
    auto ClassType = getSelfInstanceType(Instance->getType().getASTType());
    auto *CD = ClassType.getClassOrBoundGenericClass();

    return canDevirtualizeClassMethod(AI, CD);
  }

  return false;
}