//===- FunctionAttrs.cpp - Pass which marks functions attributes ----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
/// \file
/// This file implements interprocedural passes which walk the
/// call-graph deducing and/or propagating function attributes.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO/FunctionAttrs.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/SCCIterator.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/Analysis/CFG.h"
#include "llvm/Analysis/CGSCCPassManager.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/CallGraphSCCPass.h"
#include "llvm/Analysis/CaptureTracking.h"
#include "llvm/Analysis/LazyCallGraph.h"
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/ConstantRangeList.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Use.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/KnownFPClass.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Utils/Local.h"
#include <cassert>
#include <iterator>
#include <map>
#include <optional>
#include <vector>

using namespace llvm;
using namespace llvm::PatternMatch;

#define DEBUG_TYPE "function-attrs"

STATISTIC(NumMemoryAttr, "Number of functions with improved memory attribute");
STATISTIC(NumCapturesNone, "Number of arguments marked captures(none)");
STATISTIC(NumCapturesPartial, "Number of arguments marked with captures "
                              "attribute other than captures(none)");
STATISTIC(NumReturned, "Number of arguments marked returned");
STATISTIC(NumReadNoneArg, "Number of arguments marked readnone");
STATISTIC(NumReadOnlyArg, "Number of arguments marked readonly");
STATISTIC(NumWriteOnlyArg, "Number of arguments marked writeonly");
STATISTIC(NumNoAlias, "Number of function returns marked noalias");
STATISTIC(NumNonNullReturn, "Number of function returns marked nonnull");
STATISTIC(NumNoUndefReturn, "Number of function returns marked noundef");
STATISTIC(NumNoRecurse, "Number of functions marked as norecurse");
STATISTIC(NumNoUnwind, "Number of functions marked as nounwind");
STATISTIC(NumNoFree, "Number of functions marked as nofree");
STATISTIC(NumNoFreeArg, "Number of arguments marked as nofree");
STATISTIC(NumWillReturn, "Number of functions marked as willreturn");
STATISTIC(NumNoSync, "Number of functions marked as nosync");
STATISTIC(NumCold, "Number of functions marked as cold");

STATISTIC(NumThinLinkNoRecurse,
          "Number of functions marked as norecurse during thinlink");
STATISTIC(NumThinLinkNoUnwind,
          "Number of functions marked as nounwind during thinlink");

static cl::opt<bool> EnablePoisonArgAttrPropagation(
    "enable-poison-arg-attr-prop", cl::init(true), cl::Hidden,
    cl::desc("Try to propagate nonnull and nofpclass argument attributes from "
             "callsites to caller functions."));

static cl::opt<bool> DisableNoUnwindInference(
    "disable-nounwind-inference", cl::Hidden,
    cl::desc("Stop inferring nounwind attribute during function-attrs pass"));

static cl::opt<bool> DisableNoFreeInference(
    "disable-nofree-inference", cl::Hidden,
    cl::desc("Stop inferring nofree attribute during function-attrs pass"));

static cl::opt<bool> DisableThinLTOPropagation(
    "disable-thinlto-funcattrs", cl::init(true), cl::Hidden,
    cl::desc("Don't propagate function-attrs in thinLTO"));

static void addCapturesStat(CaptureInfo CI) {
  if (capturesNothing(CI))
    ++NumCapturesNone;
  else
    ++NumCapturesPartial;
}

namespace {

using SCCNodeSet = SmallSetVector<Function *, 8>;

} // end anonymous namespace

static void addLocAccess(MemoryEffects &ME, const MemoryLocation &Loc,
                         ModRefInfo MR, AAResults &AAR) {
  // Ignore accesses to known-invariant or local memory.
  MR &= AAR.getModRefInfoMask(Loc, /*IgnoreLocal=*/true);
  if (isNoModRef(MR))
    return;

  const Value *UO = getUnderlyingObjectAggressive(Loc.Ptr);
  if (isa<AllocaInst>(UO))
    return;
  if (isa<Argument>(UO)) {
    ME |= MemoryEffects::argMemOnly(MR);
    return;
  }

  // If it's not an identified object, it might be an argument.
  if (!isIdentifiedObject(UO))
    ME |= MemoryEffects::argMemOnly(MR);
  ME |= MemoryEffects(IRMemLocation::ErrnoMem, MR);
  ME |= MemoryEffects(IRMemLocation::Other, MR);
}

static void addArgLocs(MemoryEffects &ME, const CallBase *Call,
                       ModRefInfo ArgMR, AAResults &AAR) {
  for (const Value *Arg : Call->args()) {
    if (!Arg->getType()->isPtrOrPtrVectorTy())
      continue;

    addLocAccess(ME,
                 MemoryLocation::getBeforeOrAfter(Arg, Call->getAAMetadata()),
                 ArgMR, AAR);
  }
}

/// Returns the memory access attribute for function F using AAR for AA results,
/// where SCCNodes is the current SCC.
///
/// If ThisBody is true, this function may examine the function body and will
/// return a result pertaining to this copy of the function. If it is false, the
/// result will be based only on AA results for the function declaration; it
/// will be assumed that some other (perhaps less optimized) version of the
/// function may be selected at link time.
///
/// The return value is split into two parts: Memory effects that always apply,
/// and additional memory effects that apply if any of the functions in the SCC
/// can access argmem.
static std::pair<MemoryEffects, MemoryEffects>
checkFunctionMemoryAccess(Function &F, bool ThisBody, AAResults &AAR,
                          const SCCNodeSet &SCCNodes) {
  MemoryEffects OrigME = AAR.getMemoryEffects(&F);
  if (OrigME.doesNotAccessMemory())
    // Already perfect!
    return {OrigME, MemoryEffects::none()};

  if (!ThisBody)
    return {OrigME, MemoryEffects::none()};

  MemoryEffects ME = MemoryEffects::none();
  // Additional locations accessed if the SCC accesses argmem.
  MemoryEffects RecursiveArgME = MemoryEffects::none();

  auto AddNonArgMemoryEffects = [&ME](MemoryEffects InstME) {
    // Merge instruction memory effects, including inaccessible and errno
    // memory, but excluding argument memory, which is handled separately.
    ME |= InstME.getWithoutLoc(IRMemLocation::ArgMem);

    // If the instruction accesses captured memory (currently part of "other")
    // and an argument is captured (currently not tracked), then it may also
    // access argument memory.
    ModRefInfo OtherMR = InstME.getModRef(IRMemLocation::Other);
    ME |= MemoryEffects::argMemOnly(OtherMR);
  };

  // Inalloca and preallocated arguments are always clobbered by the call.
  if (F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) ||
      F.getAttributes().hasAttrSomewhere(Attribute::Preallocated))
    ME |= MemoryEffects::argMemOnly(ModRefInfo::ModRef);

  // Scan the function body for instructions that may read or write memory.
  for (Instruction &I : instructions(F)) {
    // Some instructions can be ignored even if they read or write memory.
    // Detect these now, skipping to the next instruction if one is found.
    if (auto *Call = dyn_cast<CallBase>(&I)) {
      // We can optimistically ignore calls to functions in the same SCC, with
      // two caveats:
      //  * Calls with operand bundles may have additional effects.
      //  * Argument memory accesses may imply additional effects depending on
      //    what the argument location is.
      if (!Call->hasOperandBundles() && Call->getCalledFunction() &&
          SCCNodes.count(Call->getCalledFunction())) {
        // Keep track of which additional locations are accessed if the SCC
        // turns out to access argmem.
        addArgLocs(RecursiveArgME, Call, ModRefInfo::ModRef, AAR);
        continue;
      }

      MemoryEffects CallME = AAR.getMemoryEffects(Call);

      // If the call doesn't access memory, we're done.
      if (CallME.doesNotAccessMemory())
        continue;

      // A pseudo probe call shouldn't change any function attribute since it
      // doesn't translate to a real instruction. It comes with a memory access
      // tag to prevent itself being removed by optimizations and not block
      // other instructions being optimized.
      if (isa<PseudoProbeInst>(I))
        continue;

      AddNonArgMemoryEffects(CallME);

      // Check whether all pointer arguments point to local memory, and
      // ignore calls that only access local memory.
      ModRefInfo ArgMR = CallME.getModRef(IRMemLocation::ArgMem);
      if (ArgMR != ModRefInfo::NoModRef)
        addArgLocs(ME, Call, ArgMR, AAR);
      continue;
    }

    MemoryEffects InstME = I.getMemoryEffects();
    if (InstME.doesNotAccessMemory())
      continue;

    std::optional<MemoryLocation> Loc = MemoryLocation::getOrNone(&I);
    if (!Loc) {
      // If no location is known, conservatively assume anything can be
      // accessed.
      ME |= MemoryEffects(InstME.getModRef());
      continue;
    }

    AddNonArgMemoryEffects(InstME);
    addLocAccess(ME, *Loc, InstME.getModRef(IRMemLocation::ArgMem), AAR);
  }

  return {OrigME & ME, RecursiveArgME};
}

MemoryEffects llvm::computeFunctionBodyMemoryAccess(Function &F,
                                                    AAResults &AAR) {
  return checkFunctionMemoryAccess(F, /*ThisBody=*/true, AAR, {}).first;
}

/// Deduce readonly/readnone/writeonly attributes for the SCC.
template <typename AARGetterT>
static void addMemoryAttrs(const SCCNodeSet &SCCNodes, AARGetterT &&AARGetter,
                           SmallPtrSet<Function *, 8> &Changed) {
  MemoryEffects ME = MemoryEffects::none();
  MemoryEffects RecursiveArgME = MemoryEffects::none();
  for (Function *F : SCCNodes) {
    // Call the callable parameter to look up AA results for this function.
    AAResults &AAR = AARGetter(*F);
    // Non-exact function definitions may not be selected at link time, and an
    // alternative version that writes to memory may be selected.  See the
    // comment on GlobalValue::isDefinitionExact for more details.
    auto [FnME, FnRecursiveArgME] =
        checkFunctionMemoryAccess(*F, F->hasExactDefinition(), AAR, SCCNodes);
    ME |= FnME;
    RecursiveArgME |= FnRecursiveArgME;
    // Reached bottom of the lattice, we will not be able to improve the result.
    if (ME == MemoryEffects::unknown())
      return;
  }

  // If the SCC accesses argmem, add recursive accesses resulting from that.
  ModRefInfo ArgMR = ME.getModRef(IRMemLocation::ArgMem);
  if (ArgMR != ModRefInfo::NoModRef)
    ME |= RecursiveArgME & MemoryEffects(ArgMR);

  for (Function *F : SCCNodes) {
    MemoryEffects OldME = F->getMemoryEffects();
    MemoryEffects NewME = ME & OldME;
    if (NewME != OldME) {
      ++NumMemoryAttr;
      F->setMemoryEffects(NewME);
      // Remove conflicting writable attributes.
      if (!isModSet(NewME.getModRef(IRMemLocation::ArgMem)))
        for (Argument &A : F->args())
          A.removeAttr(Attribute::Writable);
      Changed.insert(F);
    }
  }
}

// Compute definitive function attributes for a function taking into account
// prevailing definitions and linkage types
static FunctionSummary *calculatePrevailingSummary(
    ValueInfo VI,
    DenseMap<ValueInfo, FunctionSummary *> &CachedPrevailingSummary,
    function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
        IsPrevailing) {

  auto [It, Inserted] = CachedPrevailingSummary.try_emplace(VI);
  if (!Inserted)
    return It->second;

  /// At this point, prevailing symbols have been resolved. The following leads
  /// to returning a conservative result:
  /// - Multiple instances with local linkage. Normally local linkage would be
  ///   unique per module
  ///   as the GUID includes the module path. We could have a guid alias if
  ///   there wasn't any distinguishing path when each file was compiled, but
  ///   that should be rare so we'll punt on those.

  /// These next 2 cases should not happen and will assert:
  /// - Multiple instances with external linkage. This should be caught in
  ///   symbol resolution
  /// - Non-existent FunctionSummary for Aliasee. This presents a hole in our
  ///   knowledge meaning we have to go conservative.

  /// Otherwise, we calculate attributes for a function as:
  ///   1. If we have a local linkage, take its attributes. If there's somehow
  ///      multiple, bail and go conservative.
  ///   2. If we have an external/WeakODR/LinkOnceODR linkage check that it is
  ///      prevailing, take its attributes.
  ///   3. If we have a Weak/LinkOnce linkage the copies can have semantic
  ///      differences. However, if the prevailing copy is known it will be used
  ///      so take its attributes. If the prevailing copy is in a native file
  ///      all IR copies will be dead and propagation will go conservative.
  ///   4. AvailableExternally summaries without a prevailing copy are known to
  ///      occur in a couple of circumstances:
  ///      a. An internal function gets imported due to its caller getting
  ///         imported, it becomes AvailableExternally but no prevailing
  ///         definition exists. Because it has to get imported along with its
  ///         caller the attributes will be captured by propagating on its
  ///         caller.
  ///      b. C++11 [temp.explicit]p10 can generate AvailableExternally
  ///         definitions of explicitly instanced template declarations
  ///         for inlining which are ultimately dropped from the TU. Since this
  ///         is localized to the TU the attributes will have already made it to
  ///         the callers.
  ///      These are edge cases and already captured by their callers so we
  ///      ignore these for now. If they become relevant to optimize in the
  ///      future this can be revisited.
  ///   5. Otherwise, go conservative.

  FunctionSummary *Local = nullptr;
  FunctionSummary *Prevailing = nullptr;

  for (const auto &GVS : VI.getSummaryList()) {
    if (!GVS->isLive())
      continue;

    FunctionSummary *FS = dyn_cast<FunctionSummary>(GVS->getBaseObject());
    // Virtual and Unknown (e.g. indirect) calls require going conservative
    if (!FS || FS->fflags().HasUnknownCall)
      return nullptr;

    const auto &Linkage = GVS->linkage();
    if (GlobalValue::isLocalLinkage(Linkage)) {
      if (Local) {
        LLVM_DEBUG(
            dbgs()
            << "ThinLTO FunctionAttrs: Multiple Local Linkage, bailing on "
               "function "
            << VI.name() << " from " << FS->modulePath() << ". Previous module "
            << Local->modulePath() << "\n");
        return nullptr;
      }
      Local = FS;
    } else if (GlobalValue::isExternalLinkage(Linkage)) {
      assert(IsPrevailing(VI.getGUID(), GVS.get()) || GVS->wasPromoted());
      Prevailing = FS;
      break;
    } else if (GlobalValue::isWeakODRLinkage(Linkage) ||
               GlobalValue::isLinkOnceODRLinkage(Linkage) ||
               GlobalValue::isWeakAnyLinkage(Linkage) ||
               GlobalValue::isLinkOnceAnyLinkage(Linkage)) {
      if (IsPrevailing(VI.getGUID(), GVS.get())) {
        Prevailing = FS;
        break;
      }
    } else if (GlobalValue::isAvailableExternallyLinkage(Linkage)) {
      // TODO: Handle these cases if they become meaningful
      continue;
    }
  }

  auto &CPS = CachedPrevailingSummary[VI];
  if (Local) {
    assert(!Prevailing);
    CPS = Local;
  } else if (Prevailing) {
    assert(!Local);
    CPS = Prevailing;
  }

  return CPS;
}

bool llvm::thinLTOPropagateFunctionAttrs(
    ModuleSummaryIndex &Index,
    function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
        IsPrevailing) {
  // TODO: implement addNoAliasAttrs once
  // there's more information about the return type in the summary
  if (DisableThinLTOPropagation)
    return false;

  DenseMap<ValueInfo, FunctionSummary *> CachedPrevailingSummary;
  bool Changed = false;

  auto PropagateAttributes = [&](std::vector<ValueInfo> &SCCNodes) {
    // Assume we can propagate unless we discover otherwise
    FunctionSummary::FFlags InferredFlags;
    InferredFlags.NoRecurse = (SCCNodes.size() == 1);
    InferredFlags.NoUnwind = true;

    for (auto &V : SCCNodes) {
      FunctionSummary *CallerSummary =
          calculatePrevailingSummary(V, CachedPrevailingSummary, IsPrevailing);

      // Function summaries can fail to contain information such as declarations
      if (!CallerSummary)
        return;

      if (CallerSummary->fflags().MayThrow)
        InferredFlags.NoUnwind = false;

      for (const auto &Callee : CallerSummary->calls()) {
        FunctionSummary *CalleeSummary = calculatePrevailingSummary(
            Callee.first, CachedPrevailingSummary, IsPrevailing);

        if (!CalleeSummary)
          return;

        if (!CalleeSummary->fflags().NoRecurse)
          InferredFlags.NoRecurse = false;

        if (!CalleeSummary->fflags().NoUnwind)
          InferredFlags.NoUnwind = false;

        if (!InferredFlags.NoUnwind && !InferredFlags.NoRecurse)
          break;
      }
    }

    if (InferredFlags.NoUnwind || InferredFlags.NoRecurse) {
      Changed = true;
      for (auto &V : SCCNodes) {
        if (InferredFlags.NoRecurse) {
          LLVM_DEBUG(dbgs() << "ThinLTO FunctionAttrs: Propagated NoRecurse to "
                            << V.name() << "\n");
          ++NumThinLinkNoRecurse;
        }

        if (InferredFlags.NoUnwind) {
          LLVM_DEBUG(dbgs() << "ThinLTO FunctionAttrs: Propagated NoUnwind to "
                            << V.name() << "\n");
          ++NumThinLinkNoUnwind;
        }

        for (const auto &S : V.getSummaryList()) {
          if (auto *FS = dyn_cast<FunctionSummary>(S.get())) {
            if (InferredFlags.NoRecurse)
              FS->setNoRecurse();

            if (InferredFlags.NoUnwind)
              FS->setNoUnwind();
          }
        }
      }
    }
  };

  // Call propagation functions on each SCC in the Index
  for (scc_iterator<ModuleSummaryIndex *> I = scc_begin(&Index); !I.isAtEnd();
       ++I) {
    std::vector<ValueInfo> Nodes(*I);
    PropagateAttributes(Nodes);
  }
  return Changed;
}

namespace {

/// For a given pointer Argument, this retains a list of Arguments of functions
/// in the same SCC that the pointer data flows into. We use this to build an
/// SCC of the arguments.
struct ArgumentGraphNode {
  Argument *Definition;
  /// CaptureComponents for this argument, excluding captures via Uses.
  /// We don't distinguish between other/return captures here.
  CaptureComponents CC = CaptureComponents::None;
  SmallVector<ArgumentGraphNode *, 4> Uses;
};

class ArgumentGraph {
  // We store pointers to ArgumentGraphNode objects, so it's important that
  // that they not move around upon insert.
  using ArgumentMapTy = std::map<Argument *, ArgumentGraphNode>;

  ArgumentMapTy ArgumentMap;

  // There is no root node for the argument graph, in fact:
  //   void f(int *x, int *y) { if (...) f(x, y); }
  // is an example where the graph is disconnected. The SCCIterator requires a
  // single entry point, so we maintain a fake ("synthetic") root node that
  // uses every node. Because the graph is directed and nothing points into
  // the root, it will not participate in any SCCs (except for its own).
  ArgumentGraphNode SyntheticRoot;

public:
  ArgumentGraph() { SyntheticRoot.Definition = nullptr; }

  using iterator = SmallVectorImpl<ArgumentGraphNode *>::iterator;

  iterator begin() { return SyntheticRoot.Uses.begin(); }
  iterator end() { return SyntheticRoot.Uses.end(); }
  ArgumentGraphNode *getEntryNode() { return &SyntheticRoot; }

  ArgumentGraphNode *operator[](Argument *A) {
    ArgumentGraphNode &Node = ArgumentMap[A];
    Node.Definition = A;
    SyntheticRoot.Uses.push_back(&Node);
    return &Node;
  }
};

/// This tracker checks whether callees are in the SCC, and if so it does not
/// consider that a capture, instead adding it to the "Uses" list and
/// continuing with the analysis.
struct ArgumentUsesTracker : public CaptureTracker {
  ArgumentUsesTracker(const SCCNodeSet &SCCNodes) : SCCNodes(SCCNodes) {}

  void tooManyUses() override { CI = CaptureInfo::all(); }

  Action captured(const Use *U, UseCaptureInfo UseCI) override {
    if (updateCaptureInfo(U, UseCI.UseCC)) {
      // Don't bother continuing if we already capture everything.
      if (capturesAll(CI.getOtherComponents()))
        return Stop;
      return Continue;
    }

    // For SCC argument tracking, we're not going to analyze other/ret
    // components separately, so don't follow the return value.
    return ContinueIgnoringReturn;
  }

  bool updateCaptureInfo(const Use *U, CaptureComponents CC) {
    CallBase *CB = dyn_cast<CallBase>(U->getUser());
    if (!CB) {
      if (isa<ReturnInst>(U->getUser()))
        CI |= CaptureInfo::retOnly(CC);
      else
        // Conservatively assume that the captured value might make its way
        // into the return value as well. This could be made more precise.
        CI |= CaptureInfo(CC);
      return true;
    }

    Function *F = CB->getCalledFunction();
    if (!F || !F->hasExactDefinition() || !SCCNodes.count(F)) {
      CI |= CaptureInfo(CC);
      return true;
    }

    assert(!CB->isCallee(U) && "callee operand reported captured?");
    const unsigned UseIndex = CB->getDataOperandNo(U);
    if (UseIndex >= CB->arg_size()) {
      // Data operand, but not a argument operand -- must be a bundle operand
      assert(CB->hasOperandBundles() && "Must be!");

      // CaptureTracking told us that we're being captured by an operand bundle
      // use.  In this case it does not matter if the callee is within our SCC
      // or not -- we've been captured in some unknown way, and we have to be
      // conservative.
      CI |= CaptureInfo(CC);
      return true;
    }

    if (UseIndex >= F->arg_size()) {
      assert(F->isVarArg() && "More params than args in non-varargs call");
      CI |= CaptureInfo(CC);
      return true;
    }

    // TODO(captures): Could improve precision by remembering maximum
    // capture components for the argument.
    Uses.push_back(&*std::next(F->arg_begin(), UseIndex));
    return false;
  }

  // Does not include potential captures via Uses in the SCC.
  CaptureInfo CI = CaptureInfo::none();

  // Uses within our SCC.
  SmallVector<Argument *, 4> Uses;

  const SCCNodeSet &SCCNodes;
};

/// A struct of argument use: a Use and the offset it accesses. This struct
/// is to track uses inside function via GEP. If GEP has a non-constant index,
/// the Offset field is nullopt.
struct ArgumentUse {
  Use *U;
  std::optional<int64_t> Offset;
};

/// A struct of argument access info. "Unknown" accesses are the cases like
/// unrecognized instructions, instructions that have more than one use of
/// the argument, or volatile memory accesses. "WriteWithSideEffect" are call
/// instructions that not only write an argument but also capture it.
struct ArgumentAccessInfo {
  enum class AccessType : uint8_t { Write, WriteWithSideEffect, Read, Unknown };
  AccessType ArgAccessType;
  ConstantRangeList AccessRanges;
};

/// A struct to wrap the argument use info per block.
struct UsesPerBlockInfo {
  SmallDenseMap<Instruction *, ArgumentAccessInfo, 4> Insts;
  bool HasWrites = false;
  bool HasUnknownAccess = false;
};

/// A struct to summarize the argument use info in a function.
struct ArgumentUsesSummary {
  bool HasAnyWrite = false;
  bool HasWriteOutsideEntryBB = false;
  SmallDenseMap<const BasicBlock *, UsesPerBlockInfo, 16> UsesPerBlock;
};

ArgumentAccessInfo getArgumentAccessInfo(const Instruction *I,
                                         const ArgumentUse &ArgUse,
                                         const DataLayout &DL) {
  auto GetTypeAccessRange =
      [&DL](Type *Ty,
            std::optional<int64_t> Offset) -> std::optional<ConstantRange> {
    auto TypeSize = DL.getTypeStoreSize(Ty);
    if (!TypeSize.isScalable() && Offset) {
      int64_t Size = TypeSize.getFixedValue();
      APInt Low(64, *Offset, true);
      bool Overflow;
      APInt High = Low.sadd_ov(APInt(64, Size, true), Overflow);
      // Bail if the range overflows signed 64-bit int.
      if (Overflow)
        return std::nullopt;
      return ConstantRange(Low, High);
    }
    return std::nullopt;
  };
  auto GetConstantIntRange =
      [](Value *Length,
         std::optional<int64_t> Offset) -> std::optional<ConstantRange> {
    auto *ConstantLength = dyn_cast<ConstantInt>(Length);
    if (ConstantLength && Offset) {
      int64_t Len = ConstantLength->getSExtValue();

      // Reject zero or negative lengths
      if (Len <= 0)
        return std::nullopt;

      APInt Low(64, *Offset, true);
      bool Overflow;
      APInt High = Low.sadd_ov(APInt(64, Len, true), Overflow);
      if (Overflow)
        return std::nullopt;

      return ConstantRange(Low, High);
    }
    return std::nullopt;
  };

  if (auto *SI = dyn_cast<StoreInst>(I)) {
    if (SI->isSimple() && &SI->getOperandUse(1) == ArgUse.U) {
      // Get the fixed type size of "SI". Since the access range of a write
      // will be unioned, if "SI" doesn't have a fixed type size, we just set
      // the access range to empty.
      ConstantRangeList AccessRanges;
      if (auto TypeAccessRange =
              GetTypeAccessRange(SI->getAccessType(), ArgUse.Offset))
        AccessRanges.insert(*TypeAccessRange);
      return {ArgumentAccessInfo::AccessType::Write, std::move(AccessRanges)};
    }
  } else if (auto *LI = dyn_cast<LoadInst>(I)) {
    if (LI->isSimple()) {
      assert(&LI->getOperandUse(0) == ArgUse.U);
      // Get the fixed type size of "LI". Different from Write, if "LI"
      // doesn't have a fixed type size, we conservatively set as a clobber
      // with an empty access range.
      if (auto TypeAccessRange =
              GetTypeAccessRange(LI->getAccessType(), ArgUse.Offset))
        return {ArgumentAccessInfo::AccessType::Read, {*TypeAccessRange}};
    }
  } else if (auto *MemSet = dyn_cast<MemSetInst>(I)) {
    if (!MemSet->isVolatile()) {
      ConstantRangeList AccessRanges;
      if (auto AccessRange =
              GetConstantIntRange(MemSet->getLength(), ArgUse.Offset))
        AccessRanges.insert(*AccessRange);
      return {ArgumentAccessInfo::AccessType::Write, AccessRanges};
    }
  } else if (auto *MTI = dyn_cast<MemTransferInst>(I)) {
    if (!MTI->isVolatile()) {
      if (&MTI->getOperandUse(0) == ArgUse.U) {
        ConstantRangeList AccessRanges;
        if (auto AccessRange =
                GetConstantIntRange(MTI->getLength(), ArgUse.Offset))
          AccessRanges.insert(*AccessRange);
        return {ArgumentAccessInfo::AccessType::Write, AccessRanges};
      } else if (&MTI->getOperandUse(1) == ArgUse.U) {
        if (auto AccessRange =
                GetConstantIntRange(MTI->getLength(), ArgUse.Offset))
          return {ArgumentAccessInfo::AccessType::Read, {*AccessRange}};
      }
    }
  } else if (auto *CB = dyn_cast<CallBase>(I)) {
    if (CB->isArgOperand(ArgUse.U) &&
        !CB->isByValArgument(CB->getArgOperandNo(ArgUse.U))) {
      unsigned ArgNo = CB->getArgOperandNo(ArgUse.U);
      bool IsInitialize = CB->paramHasAttr(ArgNo, Attribute::Initializes);
      if (IsInitialize && ArgUse.Offset) {
        // Argument is a Write when parameter is writeonly/readnone
        // and nocapture. Otherwise, it's a WriteWithSideEffect.
        auto Access = CB->onlyWritesMemory(ArgNo) && CB->doesNotCapture(ArgNo)
                          ? ArgumentAccessInfo::AccessType::Write
                          : ArgumentAccessInfo::AccessType::WriteWithSideEffect;
        ConstantRangeList AccessRanges;
        Attribute Attr = CB->getParamAttr(ArgNo, Attribute::Initializes);
        ConstantRangeList CBCRL = Attr.getValueAsConstantRangeList();
        for (ConstantRange &CR : CBCRL)
          AccessRanges.insert(ConstantRange(CR.getLower() + *ArgUse.Offset,
                                            CR.getUpper() + *ArgUse.Offset));
        return {Access, AccessRanges};
      }
    }
  }
  // Other unrecognized instructions are considered as unknown.
  return {ArgumentAccessInfo::AccessType::Unknown, {}};
}

// Collect the uses of argument "A" in "F".
ArgumentUsesSummary collectArgumentUsesPerBlock(Argument &A, Function &F) {
  auto &DL = F.getParent()->getDataLayout();
  unsigned PointerSize =
      DL.getIndexSizeInBits(A.getType()->getPointerAddressSpace());
  ArgumentUsesSummary Result;

  BasicBlock &EntryBB = F.getEntryBlock();
  SmallVector<ArgumentUse, 4> Worklist;
  for (Use &U : A.uses())
    Worklist.push_back({&U, 0});

  // Update "UsesPerBlock" with the block of "I" as key and "Info" as value.
  // Return true if the block of "I" has write accesses after updating.
  auto UpdateUseInfo = [&Result](Instruction *I, ArgumentAccessInfo Info) {
    auto *BB = I->getParent();
    auto &BBInfo = Result.UsesPerBlock[BB];
    auto [It, Inserted] = BBInfo.Insts.try_emplace(I);
    auto &IInfo = It->second;

    // Instructions that have more than one use of the argument are considered
    // as clobbers.
    if (!Inserted) {
      IInfo = {ArgumentAccessInfo::AccessType::Unknown, {}};
      BBInfo.HasUnknownAccess = true;
      return false;
    }

    IInfo = std::move(Info);
    BBInfo.HasUnknownAccess |=
        IInfo.ArgAccessType == ArgumentAccessInfo::AccessType::Unknown;
    bool InfoHasWrites =
        (IInfo.ArgAccessType == ArgumentAccessInfo::AccessType::Write ||
         IInfo.ArgAccessType ==
             ArgumentAccessInfo::AccessType::WriteWithSideEffect) &&
        !IInfo.AccessRanges.empty();
    BBInfo.HasWrites |= InfoHasWrites;
    return InfoHasWrites;
  };

  // No need for a visited set because we don't look through phis, so there are
  // no cycles.
  while (!Worklist.empty()) {
    ArgumentUse ArgUse = Worklist.pop_back_val();
    User *U = ArgUse.U->getUser();
    // Add GEP uses to worklist.
    // If the GEP is not a constant GEP, set the ArgumentUse::Offset to nullopt.
    if (auto *GEP = dyn_cast<GEPOperator>(U)) {
      std::optional<int64_t> NewOffset = std::nullopt;
      if (ArgUse.Offset) {
        APInt Offset(PointerSize, 0);
        if (GEP->accumulateConstantOffset(DL, Offset))
          NewOffset = *ArgUse.Offset + Offset.getSExtValue();
      }
      for (Use &U : GEP->uses())
        Worklist.push_back({&U, NewOffset});
      continue;
    }

    auto *I = cast<Instruction>(U);
    bool HasWrite = UpdateUseInfo(I, getArgumentAccessInfo(I, ArgUse, DL));

    Result.HasAnyWrite |= HasWrite;

    if (HasWrite && I->getParent() != &EntryBB)
      Result.HasWriteOutsideEntryBB = true;
  }
  return Result;
}

} // end anonymous namespace

namespace llvm {

template <> struct GraphTraits<ArgumentGraphNode *> {
  using NodeRef = ArgumentGraphNode *;
  using ChildIteratorType = SmallVectorImpl<ArgumentGraphNode *>::iterator;

  static NodeRef getEntryNode(NodeRef A) { return A; }
  static ChildIteratorType child_begin(NodeRef N) { return N->Uses.begin(); }
  static ChildIteratorType child_end(NodeRef N) { return N->Uses.end(); }
};

template <>
struct GraphTraits<ArgumentGraph *> : public GraphTraits<ArgumentGraphNode *> {
  static NodeRef getEntryNode(ArgumentGraph *AG) { return AG->getEntryNode(); }

  static ChildIteratorType nodes_begin(ArgumentGraph *AG) {
    return AG->begin();
  }

  static ChildIteratorType nodes_end(ArgumentGraph *AG) { return AG->end(); }
};

struct ArgAccessProperties {
  bool IsRead = false;
  bool IsWrite = false;
  bool IsFree = false;

  static ArgAccessProperties all() { return {true, true, true}; }

  bool hasAll() const { return IsRead && IsWrite && IsFree; }

  ArgAccessProperties &operator|=(const ArgAccessProperties &Other) {
    IsRead |= Other.IsRead;
    IsWrite |= Other.IsWrite;
    IsFree |= Other.IsFree;
    return *this;
  }
};

} // end namespace llvm

/// Returns Attribute::None, Attribute::ReadOnly or Attribute::ReadNone.
static ArgAccessProperties
determinePointerAccessAttrs(Argument *A,
                            const SmallPtrSet<Argument *, 8> &SCCNodes) {
  SmallVector<Use *, 32> Worklist;
  SmallPtrSet<Use *, 32> Visited;

  // inalloca arguments are always clobbered by the call.
  if (A->hasInAllocaAttr() || A->hasPreallocatedAttr())
    return ArgAccessProperties::all();

  ArgAccessProperties Props;

  for (Use &U : A->uses()) {
    Visited.insert(&U);
    Worklist.push_back(&U);
  }

  while (!Worklist.empty()) {
    if (Props.hasAll())
      // No point in searching further..
      return Props;

    Use *U = Worklist.pop_back_val();
    Instruction *I = cast<Instruction>(U->getUser());
    if (isa<ReturnInst>(I))
      continue;

    UseCaptureInfo Info = DetermineUseCaptureKind(*U, A);

    // FIXME: This should really be part of CaptureTracking, but keep it here
    // for now due to interference with isEscapeSource().
    if (auto *CB = dyn_cast<CallBase>(I))
      if (CB->onlyReadsMemory())
        Info.UseCC &= CaptureComponents::Address;

    if (capturesAnyProvenance(Info.UseCC)) {
      // Handle indirect access via captured provenance.
      if (!capturesReadProvenanceOnly(Info.UseCC))
        return ArgAccessProperties::all();
      Props.IsRead = true;
    }

    if (capturesAnyProvenance(Info.ResultCC)) {
      for (Use &UU : I->uses())
        if (Visited.insert(&UU).second)
          Worklist.push_back(&UU);
    }

    if (auto *CB = dyn_cast<CallBase>(I)) {
      if (CB->isCallee(U)) {
        Props.IsRead = true;
        continue;
      }

      // Given we've explicitly handled the callee operand above, what's left
      // must be a data operand (e.g. argument or operand bundle)
      const unsigned UseIndex = CB->getDataOperandNo(U);

      ModRefInfo ArgMR =
          CB->getMemoryEffects().getModRef(IRMemLocation::ArgMem);
      if (isNoModRef(ArgMR))
        continue;

      if (Function *F = CB->getCalledFunction())
        if (CB->isArgOperand(U) && UseIndex < F->arg_size() &&
            SCCNodes.count(F->getArg(UseIndex)))
          // This is an argument which is part of the speculative SCC.  Note
          // that only operands corresponding to formal arguments of the callee
          // can participate in the speculation.
          continue;

      // The accessors used on call site here do the right thing for calls and
      // invokes with operand bundles.
      if (isRefSet(ArgMR) && !CB->onlyWritesMemory(UseIndex))
        Props.IsRead = true;
      if (isModSet(ArgMR) && !CB->onlyReadsMemory(UseIndex)) {
        Props.IsWrite = true;
        if (CB->isArgOperand(U) && !CB->hasFnAttr(Attribute::NoFree) &&
            !CB->paramHasAttr(UseIndex, Attribute::NoFree) &&
            !CB->paramHasAttr(UseIndex, Attribute::NoFreeObj))
          Props.IsFree = true;
      }
    } else {
      // Ignore value operand for stores.
      if (isa<StoreInst>(I) &&
          StoreInst::getPointerOperandIndex() != U->getOperandNo())
        continue;

      Props.IsRead |= I->mayReadFromMemory();
      Props.IsWrite |= I->mayWriteToMemory();
    }
  }

  return Props;
}

/// Deduce returned attributes for the SCC.
static void addArgumentReturnedAttrs(const SCCNodeSet &SCCNodes,
                                     SmallPtrSet<Function *, 8> &Changed) {
  // Check each function in turn, determining if an argument is always returned.
  for (Function *F : SCCNodes) {
    // We can infer and propagate function attributes only when we know that the
    // definition we'll get at link time is *exactly* the definition we see now.
    // For more details, see GlobalValue::mayBeDerefined.
    if (!F->hasExactDefinition())
      continue;

    if (F->getReturnType()->isVoidTy())
      continue;

    // There is nothing to do if an argument is already marked as 'returned'.
    if (F->getAttributes().hasAttrSomewhere(Attribute::Returned))
      continue;

    auto FindRetArg = [&]() -> Argument * {
      Argument *RetArg = nullptr;
      for (BasicBlock &BB : *F)
        if (auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator())) {
          // Note that stripPointerCasts should look through functions with
          // returned arguments.
          auto *RetVal =
              dyn_cast<Argument>(Ret->getReturnValue()->stripPointerCasts());
          if (!RetVal || RetVal->getType() != F->getReturnType())
            return nullptr;

          if (!RetArg)
            RetArg = RetVal;
          else if (RetArg != RetVal)
            return nullptr;
        }

      return RetArg;
    };

    if (Argument *RetArg = FindRetArg()) {
      RetArg->addAttr(Attribute::Returned);
      ++NumReturned;
      Changed.insert(F);
    }
  }
}

/// If a callsite has arguments that are also arguments to the parent function,
/// try to propagate attributes from the callsite's arguments to the parent's
/// arguments. This may be important because inlining can cause information loss
/// when attribute knowledge disappears with the inlined call.
static bool addArgumentAttrsFromCallsites(Function &F) {
  if (!EnablePoisonArgAttrPropagation)
    return false;

  bool Changed = false;

  // For an argument attribute to transfer from a callsite to the parent, the
  // call must be guaranteed to execute every time the parent is called.
  // Conservatively, just check for calls in the entry block that are guaranteed
  // to execute.
  // TODO: This could be enhanced by testing if the callsite post-dominates the
  // entry block or by doing simple forward walks or backward walks to the
  // callsite.
  BasicBlock &Entry = F.getEntryBlock();
  for (Instruction &I : Entry) {
    if (auto *CB = dyn_cast<CallBase>(&I)) {
      if (auto *CalledFunc = CB->getCalledFunction()) {
        for (auto &CSArg : CalledFunc->args()) {
          unsigned ArgNo = CSArg.getArgNo();
          auto *FArg = dyn_cast<Argument>(CB->getArgOperand(ArgNo));
          if (!FArg)
            continue;

          if (CSArg.hasNonNullAttr(/*AllowUndefOrPoison=*/false)) {
            // If the non-null callsite argument operand is an argument to 'F'
            // (the caller) and the call is guaranteed to execute, then the
            // value must be non-null throughout 'F'.
            if (!FArg->hasNonNullAttr()) {
              FArg->addAttr(Attribute::NonNull);
              Changed = true;
            }
          } else if (FPClassTest CSNoFPClass = CB->getParamNoFPClass(ArgNo);
                     CSNoFPClass != fcNone &&
                     CB->paramHasAttr(ArgNo, Attribute::NoUndef)) {
            FPClassTest ArgNoFPClass = FArg->getNoFPClass();

            if ((CSNoFPClass | ArgNoFPClass) != ArgNoFPClass) {
              FArg->addAttr(Attribute::getWithNoFPClass(
                  FArg->getContext(), CSNoFPClass | ArgNoFPClass));
              Changed = true;
            }
          }
        }
      }
    }
    if (!isGuaranteedToTransferExecutionToSuccessor(&I))
      break;
  }

  return Changed;
}

static bool addAccessAttrs(Argument *A, ArgAccessProperties Props) {
  assert(A && "Argument must not be null.");

  bool Changed = false;
  if (!Props.IsFree && !A->hasAttribute(Attribute::NoFree) &&
      !A->hasAttribute(Attribute::NoFreeObj)) {
    ++NumNoFreeArg;
    A->addAttr(Attribute::NoFree);
    Changed = true;
  }

  if (Props.IsRead && Props.IsWrite)
    return Changed;

  Attribute::AttrKind Attr;
  if (Props.IsRead)
    Attr = Attribute::ReadOnly;
  else if (Props.IsWrite)
    Attr = Attribute::WriteOnly;
  else
    Attr = Attribute::ReadNone;

  // If the argument already has the attribute, nothing needs to be done.
  if (A->hasAttribute(Attr))
    return false;

  // Otherwise, remove potentially conflicting attribute, add the new one,
  // and update statistics.
  A->removeAttr(Attribute::WriteOnly);
  A->removeAttr(Attribute::ReadOnly);
  A->removeAttr(Attribute::ReadNone);
  // Remove conflicting writable attribute.
  if (Attr == Attribute::ReadNone || Attr == Attribute::ReadOnly)
    A->removeAttr(Attribute::Writable);
  A->addAttr(Attr);
  if (Attr == Attribute::ReadOnly)
    ++NumReadOnlyArg;
  else if (Attr == Attribute::WriteOnly)
    ++NumWriteOnlyArg;
  else
    ++NumReadNoneArg;
  return true;
}

static bool inferInitializes(Argument &A, Function &F) {
  auto ArgumentUses = collectArgumentUsesPerBlock(A, F);
  // No write anywhere in the function, bail.
  if (!ArgumentUses.HasAnyWrite)
    return false;

  auto &UsesPerBlock = ArgumentUses.UsesPerBlock;
  BasicBlock &EntryBB = F.getEntryBlock();
  // A map to store the argument ranges initialized by a BasicBlock (including
  // its successors).
  DenseMap<const BasicBlock *, ConstantRangeList> Initialized;
  // Visit the successors of "BB" block and the instructions in BB (post-order)
  // to get the argument ranges initialized by "BB" (including its successors).
  // The result will be cached in "Initialized".
  auto VisitBlock = [&](const BasicBlock *BB) -> ConstantRangeList {
    auto UPB = UsesPerBlock.find(BB);
    ConstantRangeList CRL;

    // Start with intersection of successors.
    // If this block has any clobbering use, we're going to clear out the
    // ranges at some point in this block anyway, so don't bother looking at
    // successors.
    if (UPB == UsesPerBlock.end() || !UPB->second.HasUnknownAccess) {
      bool HasAddedSuccessor = false;
      for (auto *Succ : successors(BB)) {
        if (auto SuccI = Initialized.find(Succ); SuccI != Initialized.end()) {
          if (HasAddedSuccessor) {
            CRL = CRL.intersectWith(SuccI->second);
          } else {
            CRL = SuccI->second;
            HasAddedSuccessor = true;
          }
        } else {
          CRL = ConstantRangeList();
          break;
        }
      }
    }

    if (UPB != UsesPerBlock.end()) {
      // Sort uses in this block by instruction order.
      SmallVector<std::pair<Instruction *, ArgumentAccessInfo>, 2> Insts;
      append_range(Insts, UPB->second.Insts);
      sort(Insts, [](std::pair<Instruction *, ArgumentAccessInfo> &LHS,
                     std::pair<Instruction *, ArgumentAccessInfo> &RHS) {
        return LHS.first->comesBefore(RHS.first);
      });

      // From the end of the block to the beginning of the block, set
      // initializes ranges.
      for (auto &[_, Info] : reverse(Insts)) {
        if (Info.ArgAccessType == ArgumentAccessInfo::AccessType::Unknown ||
            Info.ArgAccessType ==
                ArgumentAccessInfo::AccessType::WriteWithSideEffect)
          CRL = ConstantRangeList();
        if (!Info.AccessRanges.empty()) {
          if (Info.ArgAccessType == ArgumentAccessInfo::AccessType::Write ||
              Info.ArgAccessType ==
                  ArgumentAccessInfo::AccessType::WriteWithSideEffect) {
            CRL = CRL.unionWith(Info.AccessRanges);
          } else {
            assert(Info.ArgAccessType == ArgumentAccessInfo::AccessType::Read);
            for (const auto &ReadRange : Info.AccessRanges)
              CRL.subtract(ReadRange);
          }
        }
      }
    }
    return CRL;
  };

  ConstantRangeList EntryCRL;
  // If all write instructions are in the EntryBB, or if the EntryBB has
  // a clobbering use, we only need to look at EntryBB.
  bool OnlyScanEntryBlock = !ArgumentUses.HasWriteOutsideEntryBB;
  if (!OnlyScanEntryBlock)
    if (auto EntryUPB = UsesPerBlock.find(&EntryBB);
        EntryUPB != UsesPerBlock.end())
      OnlyScanEntryBlock = EntryUPB->second.HasUnknownAccess;
  if (OnlyScanEntryBlock) {
    EntryCRL = VisitBlock(&EntryBB);
    if (EntryCRL.empty())
      return false;
  } else {
    // Now we have to go through CFG to get the initialized argument ranges
    // across blocks. With dominance and post-dominance, the initialized ranges
    // by a block include both accesses inside this block and accesses in its
    // (transitive) successors. So visit successors before predecessors with a
    // post-order walk of the blocks and memorize the results in "Initialized".
    for (const BasicBlock *BB : post_order(&F)) {
      ConstantRangeList CRL = VisitBlock(BB);
      if (!CRL.empty())
        Initialized[BB] = CRL;
    }

    auto EntryCRLI = Initialized.find(&EntryBB);
    if (EntryCRLI == Initialized.end())
      return false;

    EntryCRL = EntryCRLI->second;
  }

  assert(!EntryCRL.empty() &&
         "should have bailed already if EntryCRL is empty");

  if (A.hasAttribute(Attribute::Initializes)) {
    ConstantRangeList PreviousCRL =
        A.getAttribute(Attribute::Initializes).getValueAsConstantRangeList();
    if (PreviousCRL == EntryCRL)
      return false;
    EntryCRL = EntryCRL.unionWith(PreviousCRL);
  }

  A.addAttr(Attribute::get(A.getContext(), Attribute::Initializes,
                           EntryCRL.rangesRef()));

  return true;
}

/// Deduce nocapture attributes for the SCC.
static void addArgumentAttrs(const SCCNodeSet &SCCNodes,
                             SmallPtrSet<Function *, 8> &Changed,
                             bool SkipInitializes) {
  ArgumentGraph AG;

  auto DetermineAccessAttrsForSingleton = [](Argument *A) {
    SmallPtrSet<Argument *, 8> Self;
    Self.insert(A);
    return addAccessAttrs(A, determinePointerAccessAttrs(A, Self));
  };

  // Check each function in turn, determining which pointer arguments are not
  // captured.
  for (Function *F : SCCNodes) {
    // We can infer and propagate function attributes only when we know that the
    // definition we'll get at link time is *exactly* the definition we see now.
    // For more details, see GlobalValue::mayBeDerefined.
    if (!F->hasExactDefinition())
      continue;

    if (addArgumentAttrsFromCallsites(*F))
      Changed.insert(F);

    // Functions that are readonly (or readnone) and nounwind and don't return
    // a value can't capture arguments. Don't analyze them.
    if (F->onlyReadsMemory() && F->doesNotThrow() && F->willReturn() &&
        F->getReturnType()->isVoidTy()) {
      for (Argument &A : F->args()) {
        if (A.getType()->isPointerTy() && !A.hasNoCaptureAttr()) {
          A.addAttr(Attribute::getWithCaptureInfo(A.getContext(),
                                                  CaptureInfo::none()));
          ++NumCapturesNone;
          Changed.insert(F);
        }
      }
      continue;
    }

    for (Argument &A : F->args()) {
      if (!A.getType()->isPointerTy())
        continue;
      bool HasNonLocalUses = false;
      CaptureInfo OrigCI = A.getAttributes().getCaptureInfo();
      if (!capturesNothing(OrigCI)) {
        ArgumentUsesTracker Tracker(SCCNodes);
        PointerMayBeCaptured(&A, &Tracker);
        CaptureInfo NewCI = Tracker.CI & OrigCI;
        if (NewCI != OrigCI) {
          if (Tracker.Uses.empty()) {
            // If the information is complete, add the attribute now.
            A.addAttr(Attribute::getWithCaptureInfo(A.getContext(), NewCI));
            addCapturesStat(NewCI);
            Changed.insert(F);
          } else {
            // If it's not trivially captured and not trivially not captured,
            // then it must be calling into another function in our SCC. Save
            // its particulars for Argument-SCC analysis later.
            ArgumentGraphNode *Node = AG[&A];
            Node->CC = CaptureComponents(NewCI);
            for (Argument *Use : Tracker.Uses) {
              Node->Uses.push_back(AG[Use]);
              if (Use != &A)
                HasNonLocalUses = true;
            }
          }
        }
        // Otherwise, it's captured. Don't bother doing SCC analysis on it.
      }
      if (!HasNonLocalUses && !A.onlyReadsMemory()) {
        // Can we determine that it's readonly/readnone/writeonly without doing
        // an SCC? Note that we don't allow any calls at all here, or else our
        // result will be dependent on the iteration order through the
        // functions in the SCC.
        if (DetermineAccessAttrsForSingleton(&A))
          Changed.insert(F);
      }
      if (!SkipInitializes && !A.onlyReadsMemory()) {
        if (inferInitializes(A, *F))
          Changed.insert(F);
      }
    }
  }

  // The graph we've collected is partial because we stopped scanning for
  // argument uses once we solved the argument trivially. These partial nodes
  // show up as ArgumentGraphNode objects with an empty Uses list, and for
  // these nodes the final decision about whether they capture has already been
  // made.  If the definition doesn't have a 'nocapture' attribute by now, it
  // captures.

  for (scc_iterator<ArgumentGraph *> I = scc_begin(&AG); !I.isAtEnd(); ++I) {
    const std::vector<ArgumentGraphNode *> &ArgumentSCC = *I;
    if (ArgumentSCC.size() == 1) {
      if (!ArgumentSCC[0]->Definition)
        continue; // synthetic root node

      // eg. "void f(int* x) { if (...) f(x); }"
      if (ArgumentSCC[0]->Uses.size() == 1 &&
          ArgumentSCC[0]->Uses[0] == ArgumentSCC[0]) {
        Argument *A = ArgumentSCC[0]->Definition;
        CaptureInfo OrigCI = A->getAttributes().getCaptureInfo();
        CaptureInfo NewCI = CaptureInfo(ArgumentSCC[0]->CC) & OrigCI;
        if (NewCI != OrigCI) {
          A->addAttr(Attribute::getWithCaptureInfo(A->getContext(), NewCI));
          addCapturesStat(NewCI);
          Changed.insert(A->getParent());
        }

        // Infer the access attributes given the new captures one
        if (DetermineAccessAttrsForSingleton(A))
          Changed.insert(A->getParent());
      }
      continue;
    }

    SmallPtrSet<Argument *, 8> ArgumentSCCNodes;
    // Fill ArgumentSCCNodes with the elements of the ArgumentSCC.  Used for
    // quickly looking up whether a given Argument is in this ArgumentSCC.
    for (ArgumentGraphNode *I : ArgumentSCC) {
      ArgumentSCCNodes.insert(I->Definition);
    }

    // At the SCC level, only track merged CaptureComponents. We're not
    // currently prepared to handle propagation of return-only captures across
    // the SCC.
    CaptureComponents CC = CaptureComponents::None;
    for (ArgumentGraphNode *N : ArgumentSCC) {
      for (ArgumentGraphNode *Use : N->Uses) {
        Argument *A = Use->Definition;
        if (ArgumentSCCNodes.count(A))
          CC |= Use->CC;
        else
          CC |= CaptureComponents(A->getAttributes().getCaptureInfo());
        break;
      }
      if (capturesAll(CC))
        break;
    }

    if (!capturesAll(CC)) {
      for (ArgumentGraphNode *N : ArgumentSCC) {
        Argument *A = N->Definition;
        CaptureInfo OrigCI = A->getAttributes().getCaptureInfo();
        CaptureInfo NewCI = CaptureInfo(N->CC | CC) & OrigCI;
        if (NewCI != OrigCI) {
          A->addAttr(Attribute::getWithCaptureInfo(A->getContext(), NewCI));
          addCapturesStat(NewCI);
          Changed.insert(A->getParent());
        }
      }
    }

    if (capturesAnyProvenance(CC)) {
      // As the pointer provenance may be captured, determine the pointer
      // attributes looking at each argument individually.
      for (ArgumentGraphNode *N : ArgumentSCC) {
        if (DetermineAccessAttrsForSingleton(N->Definition))
          Changed.insert(N->Definition->getParent());
      }
      continue;
    }

    // We also want to compute readonly/readnone/writeonly. With a small number
    // of false negatives, we can assume that any pointer which is captured
    // isn't going to be provably readonly or readnone, since by definition
    // we can't analyze all uses of a captured pointer.
    //
    // The false negatives happen when the pointer is captured by a function
    // that promises readonly/readnone behaviour on the pointer, then the
    // pointer's lifetime ends before anything that writes to arbitrary memory.
    // Also, a readonly/readnone pointer may be returned, but returning a
    // pointer is capturing it.

    ArgAccessProperties Props;
    for (ArgumentGraphNode *N : ArgumentSCC) {
      Argument *A = N->Definition;
      Props |= determinePointerAccessAttrs(A, ArgumentSCCNodes);
      if (Props.hasAll())
        break;
    }

    if (!Props.hasAll()) {
      for (ArgumentGraphNode *N : ArgumentSCC) {
        Argument *A = N->Definition;
        if (addAccessAttrs(A, Props))
          Changed.insert(A->getParent());
      }
    }
  }
}

/// Tests whether a function is "malloc-like".
///
/// A function is "malloc-like" if it returns either null or a pointer that
/// doesn't alias any other pointer visible to the caller.
static bool isFunctionMallocLike(Function *F, const SCCNodeSet &SCCNodes) {
  SmallSetVector<Value *, 8> FlowsToReturn;
  for (BasicBlock &BB : *F)
    if (ReturnInst *Ret = dyn_cast<ReturnInst>(BB.getTerminator()))
      FlowsToReturn.insert(Ret->getReturnValue());

  for (unsigned i = 0; i != FlowsToReturn.size(); ++i) {
    Value *RetVal = FlowsToReturn[i];

    if (Constant *C = dyn_cast<Constant>(RetVal)) {
      if (!C->isNullValue() && !isa<UndefValue>(C))
        return false;

      continue;
    }

    if (isa<Argument>(RetVal))
      return false;

    if (Instruction *RVI = dyn_cast<Instruction>(RetVal))
      switch (RVI->getOpcode()) {
      // Extend the analysis by looking upwards.
      case Instruction::BitCast:
      case Instruction::GetElementPtr:
      case Instruction::AddrSpaceCast:
        FlowsToReturn.insert(RVI->getOperand(0));
        continue;
      case Instruction::Select: {
        SelectInst *SI = cast<SelectInst>(RVI);
        FlowsToReturn.insert(SI->getTrueValue());
        FlowsToReturn.insert(SI->getFalseValue());
        continue;
      }
      case Instruction::PHI: {
        PHINode *PN = cast<PHINode>(RVI);
        FlowsToReturn.insert_range(PN->incoming_values());
        continue;
      }

      // Check whether the pointer came from an allocation.
      case Instruction::Alloca:
        break;
      case Instruction::Call:
      case Instruction::Invoke: {
        CallBase &CB = cast<CallBase>(*RVI);
        if (CB.hasRetAttr(Attribute::NoAlias))
          break;
        if (CB.getCalledFunction() && SCCNodes.count(CB.getCalledFunction()))
          break;
        [[fallthrough]];
      }
      default:
        return false; // Did not come from an allocation.
      }

    if (PointerMayBeCaptured(RetVal, /*ReturnCaptures=*/false))
      return false;
  }

  return true;
}

/// Deduce noalias attributes for the SCC.
static void addNoAliasAttrs(const SCCNodeSet &SCCNodes,
                            SmallPtrSet<Function *, 8> &Changed) {
  // Check each function in turn, determining which functions return noalias
  // pointers.
  for (Function *F : SCCNodes) {
    // Already noalias.
    if (F->returnDoesNotAlias())
      continue;

    // We can infer and propagate function attributes only when we know that the
    // definition we'll get at link time is *exactly* the definition we see now.
    // For more details, see GlobalValue::mayBeDerefined.
    if (!F->hasExactDefinition())
      return;

    // We annotate noalias return values, which are only applicable to
    // pointer types.
    if (!F->getReturnType()->isPointerTy())
      continue;

    if (!isFunctionMallocLike(F, SCCNodes))
      return;
  }

  for (Function *F : SCCNodes) {
    if (F->returnDoesNotAlias() ||
        !F->getReturnType()->isPointerTy())
      continue;

    F->setReturnDoesNotAlias();
    ++NumNoAlias;
    Changed.insert(F);
  }
}

/// Tests whether this function is known to not return null.
///
/// Requires that the function returns a pointer.
///
/// Returns true if it believes the function will not return a null, and sets
/// \p Speculative based on whether the returned conclusion is a speculative
/// conclusion due to SCC calls.
static bool isReturnNonNull(Function *F, const SCCNodeSet &SCCNodes,
                            bool &Speculative) {
  assert(F->getReturnType()->isPointerTy() &&
         "nonnull only meaningful on pointer types");
  Speculative = false;

  SmallSetVector<Value *, 8> FlowsToReturn;
  for (BasicBlock &BB : *F)
    if (auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator()))
      FlowsToReturn.insert(Ret->getReturnValue());

  auto &DL = F->getDataLayout();

  for (unsigned i = 0; i != FlowsToReturn.size(); ++i) {
    Value *RetVal = FlowsToReturn[i];

    // If this value is locally known to be non-null, we're good
    if (isKnownNonZero(RetVal, DL))
      continue;

    // Otherwise, we need to look upwards since we can't make any local
    // conclusions.
    Instruction *RVI = dyn_cast<Instruction>(RetVal);
    if (!RVI)
      return false;
    switch (RVI->getOpcode()) {
    // Extend the analysis by looking upwards.
    case Instruction::BitCast:
    case Instruction::AddrSpaceCast:
      FlowsToReturn.insert(RVI->getOperand(0));
      continue;
    case Instruction::GetElementPtr:
      if (cast<GEPOperator>(RVI)->isInBounds()) {
        FlowsToReturn.insert(RVI->getOperand(0));
        continue;
      }
      return false;
    case Instruction::Select: {
      SelectInst *SI = cast<SelectInst>(RVI);
      FlowsToReturn.insert(SI->getTrueValue());
      FlowsToReturn.insert(SI->getFalseValue());
      continue;
    }
    case Instruction::PHI: {
      PHINode *PN = cast<PHINode>(RVI);
      for (int i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
        FlowsToReturn.insert(PN->getIncomingValue(i));
      continue;
    }
    case Instruction::Call:
    case Instruction::Invoke: {
      CallBase &CB = cast<CallBase>(*RVI);
      Function *Callee = CB.getCalledFunction();
      // A call to a node within the SCC is assumed to return null until
      // proven otherwise
      if (Callee && SCCNodes.count(Callee)) {
        Speculative = true;
        continue;
      }
      return false;
    }
    default:
      return false; // Unknown source, may be null
    };
    llvm_unreachable("should have either continued or returned");
  }

  return true;
}

/// Deduce nonnull attributes for the SCC.
static void addNonNullAttrs(const SCCNodeSet &SCCNodes,
                            SmallPtrSet<Function *, 8> &Changed) {
  // Speculative that all functions in the SCC return only nonnull
  // pointers.  We may refute this as we analyze functions.
  bool SCCReturnsNonNull = true;

  // Check each function in turn, determining which functions return nonnull
  // pointers.
  for (Function *F : SCCNodes) {
    // Already nonnull.
    if (F->getAttributes().hasRetAttr(Attribute::NonNull))
      continue;

    // We can infer and propagate function attributes only when we know that the
    // definition we'll get at link time is *exactly* the definition we see now.
    // For more details, see GlobalValue::mayBeDerefined.
    if (!F->hasExactDefinition())
      return;

    // We annotate nonnull return values, which are only applicable to
    // pointer types.
    if (!F->getReturnType()->isPointerTy())
      continue;

    bool Speculative = false;
    if (isReturnNonNull(F, SCCNodes, Speculative)) {
      if (!Speculative) {
        // Mark the function eagerly since we may discover a function
        // which prevents us from speculating about the entire SCC
        LLVM_DEBUG(dbgs() << "Eagerly marking " << F->getName()
                          << " as nonnull\n");
        F->addRetAttr(Attribute::NonNull);
        ++NumNonNullReturn;
        Changed.insert(F);
      }
      continue;
    }
    // At least one function returns something which could be null, can't
    // speculate any more.
    SCCReturnsNonNull = false;
  }

  if (SCCReturnsNonNull) {
    for (Function *F : SCCNodes) {
      if (F->getAttributes().hasRetAttr(Attribute::NonNull) ||
          !F->getReturnType()->isPointerTy())
        continue;

      LLVM_DEBUG(dbgs() << "SCC marking " << F->getName() << " as nonnull\n");
      F->addRetAttr(Attribute::NonNull);
      ++NumNonNullReturn;
      Changed.insert(F);
    }
  }
}

/// Deduce noundef attributes for the SCC.
static void addNoUndefAttrs(const SCCNodeSet &SCCNodes,
                            SmallPtrSet<Function *, 8> &Changed) {
  // Check each function in turn, determining which functions return noundef
  // values.
  for (Function *F : SCCNodes) {
    // Already noundef.
    AttributeList Attrs = F->getAttributes();
    if (Attrs.hasRetAttr(Attribute::NoUndef))
      continue;

    // We can infer and propagate function attributes only when we know that the
    // definition we'll get at link time is *exactly* the definition we see now.
    // For more details, see GlobalValue::mayBeDerefined.
    if (!F->hasExactDefinition())
      return;

    // MemorySanitizer assumes that the definition and declaration of a
    // function will be consistent. A function with sanitize_memory attribute
    // should be skipped from inference.
    if (F->hasFnAttribute(Attribute::SanitizeMemory))
      continue;

    if (F->getReturnType()->isVoidTy())
      continue;

    const DataLayout &DL = F->getDataLayout();
    if (all_of(*F, [&](BasicBlock &BB) {
          if (auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator())) {
            // TODO: perform context-sensitive analysis?
            Value *RetVal = Ret->getReturnValue();
            if (!isGuaranteedNotToBeUndefOrPoison(RetVal))
              return false;

            // We know the original return value is not poison now, but it
            // could still be converted to poison by another return attribute.
            // Try to explicitly re-prove the relevant attributes.
            if (Attrs.hasRetAttr(Attribute::NonNull) &&
                !isKnownNonZero(RetVal, DL))
              return false;

            if (MaybeAlign Align = Attrs.getRetAlignment())
              if (RetVal->getPointerAlignment(DL) < *Align)
                return false;

            Attribute Attr = Attrs.getRetAttr(Attribute::Range);
            if (Attr.isValid() &&
                !Attr.getRange().contains(
                    computeConstantRange(RetVal, /*ForSigned=*/false,
                                         SimplifyQuery(F->getDataLayout()))))
              return false;

            FPClassTest AttrFPClass = Attrs.getRetNoFPClass();
            if (AttrFPClass != fcNone) {
              KnownFPClass ComputedFPClass = computeKnownFPClass(RetVal, DL);
              if (!ComputedFPClass.isKnownNever(AttrFPClass))
                return false;
            }
          }
          return true;
        })) {
      F->addRetAttr(Attribute::NoUndef);
      ++NumNoUndefReturn;
      Changed.insert(F);
    }
  }
}

namespace {

/// Collects a set of attribute inference requests and performs them all in one
/// go on a single SCC Node. Inference involves scanning function bodies
/// looking for instructions that violate attribute assumptions.
/// As soon as all the bodies are fine we are free to set the attribute.
/// Customization of inference for individual attributes is performed by
/// providing a handful of predicates for each attribute.
class AttributeInferer {
public:
  /// Describes a request for inference of a single attribute.
  struct InferenceDescriptor {

    /// Returns true if this function does not have to be handled.
    /// General intent for this predicate is to provide an optimization
    /// for functions that do not need this attribute inference at all
    /// (say, for functions that already have the attribute).
    std::function<bool(const Function &)> SkipFunction;

    /// Returns true if this instruction violates attribute assumptions.
    std::function<bool(Instruction &)> InstrBreaksAttribute;

    /// Sets the inferred attribute for this function.
    std::function<void(Function &)> SetAttribute;

    /// Attribute we derive.
    Attribute::AttrKind AKind;

    /// If true, only "exact" definitions can be used to infer this attribute.
    /// See GlobalValue::isDefinitionExact.
    bool RequiresExactDefinition;

    InferenceDescriptor(Attribute::AttrKind AK,
                        std::function<bool(const Function &)> SkipFunc,
                        std::function<bool(Instruction &)> InstrScan,
                        std::function<void(Function &)> SetAttr,
                        bool ReqExactDef)
        : SkipFunction(SkipFunc), InstrBreaksAttribute(InstrScan),
          SetAttribute(SetAttr), AKind(AK),
          RequiresExactDefinition(ReqExactDef) {}
  };

private:
  SmallVector<InferenceDescriptor, 4> InferenceDescriptors;

public:
  void registerAttrInference(InferenceDescriptor AttrInference) {
    InferenceDescriptors.push_back(AttrInference);
  }

  void run(const SCCNodeSet &SCCNodes, SmallPtrSet<Function *, 8> &Changed);
};

/// Perform all the requested attribute inference actions according to the
/// attribute predicates stored before.
void AttributeInferer::run(const SCCNodeSet &SCCNodes,
                           SmallPtrSet<Function *, 8> &Changed) {
  SmallVector<InferenceDescriptor, 4> InferInSCC = InferenceDescriptors;
  // Go through all the functions in SCC and check corresponding attribute
  // assumptions for each of them. Attributes that are invalid for this SCC
  // will be removed from InferInSCC.
  for (Function *F : SCCNodes) {

    // No attributes whose assumptions are still valid - done.
    if (InferInSCC.empty())
      return;

    // Check if our attributes ever need scanning/can be scanned.
    llvm::erase_if(InferInSCC, [F](const InferenceDescriptor &ID) {
      if (ID.SkipFunction(*F))
        return false;

      // Remove from further inference (invalidate) when visiting a function
      // that has no instructions to scan/has an unsuitable definition.
      return F->isDeclaration() ||
             (ID.RequiresExactDefinition && !F->hasExactDefinition());
    });

    // For each attribute still in InferInSCC that doesn't explicitly skip F,
    // set up the F instructions scan to verify assumptions of the attribute.
    SmallVector<InferenceDescriptor, 4> InferInThisFunc;
    llvm::copy_if(
        InferInSCC, std::back_inserter(InferInThisFunc),
        [F](const InferenceDescriptor &ID) { return !ID.SkipFunction(*F); });

    if (InferInThisFunc.empty())
      continue;

    // Start instruction scan.
    for (Instruction &I : instructions(*F)) {
      llvm::erase_if(InferInThisFunc, [&](const InferenceDescriptor &ID) {
        if (!ID.InstrBreaksAttribute(I))
          return false;
        // Remove attribute from further inference on any other functions
        // because attribute assumptions have just been violated.
        llvm::erase_if(InferInSCC, [&ID](const InferenceDescriptor &D) {
          return D.AKind == ID.AKind;
        });
        // Remove attribute from the rest of current instruction scan.
        return true;
      });

      if (InferInThisFunc.empty())
        break;
    }
  }

  if (InferInSCC.empty())
    return;

  for (Function *F : SCCNodes)
    // At this point InferInSCC contains only functions that were either:
    //   - explicitly skipped from scan/inference, or
    //   - verified to have no instructions that break attribute assumptions.
    // Hence we just go and force the attribute for all non-skipped functions.
    for (auto &ID : InferInSCC) {
      if (ID.SkipFunction(*F))
        continue;
      Changed.insert(F);
      ID.SetAttribute(*F);
    }
}

struct SCCNodesResult {
  SCCNodeSet SCCNodes;
};

} // end anonymous namespace

/// Helper for non-Convergent inference predicate InstrBreaksAttribute.
static bool InstrBreaksNonConvergent(Instruction &I,
                                     const SCCNodeSet &SCCNodes) {
  const CallBase *CB = dyn_cast<CallBase>(&I);
  // Breaks non-convergent assumption if CS is a convergent call to a function
  // not in the SCC.
  return CB && CB->isConvergent() &&
         !SCCNodes.contains(CB->getCalledFunction());
}

/// Helper for NoUnwind inference predicate InstrBreaksAttribute.
static bool InstrBreaksNonThrowing(Instruction &I, const SCCNodeSet &SCCNodes) {
  if (!I.mayThrow(/* IncludePhaseOneUnwind */ true))
    return false;
  if (const auto *CI = dyn_cast<CallInst>(&I)) {
    if (Function *Callee = CI->getCalledFunction()) {
      // I is a may-throw call to a function inside our SCC. This doesn't
      // invalidate our current working assumption that the SCC is no-throw; we
      // just have to scan that other function.
      if (SCCNodes.contains(Callee))
        return false;
    }
  }
  return true;
}

/// Helper for NoFree inference predicate InstrBreaksAttribute.
static bool InstrBreaksNoFree(Instruction &I, const SCCNodeSet &SCCNodes) {
  CallBase *CB = dyn_cast<CallBase>(&I);
  if (!CB) {
    // Synchronization may establish happens-before with a free on another
    // thread.
    return I.maySynchronize();
  }

  if (CB->hasFnAttr(Attribute::NoFree))
    return false;

  // Speculatively assume in SCC.
  if (Function *Callee = CB->getCalledFunction())
    if (SCCNodes.contains(Callee))
      return false;

  return true;
}

static bool InstrBreaksNoSync(Instruction &I, const SCCNodeSet &SCCNodes) {
  if (!I.maySynchronize())
    return false;

  // Optimistically assume calls within the SCC are nosync: if nothing else in
  // the SCC synchronizes, the assumption holds.
  if (auto *CB = dyn_cast<CallBase>(&I))
    if (Function *Callee = CB->getCalledFunction())
      if (SCCNodes.contains(Callee))
        return false;

  return true;
}

/// Attempt to remove convergent function attribute when possible.
///
/// Returns true if any changes to function attributes were made.
static void inferConvergent(const SCCNodeSet &SCCNodes,
                            SmallPtrSet<Function *, 8> &Changed) {
  AttributeInferer AI;

  // Request to remove the convergent attribute from all functions in the SCC
  // if every callsite within the SCC is not convergent (except for calls
  // to functions within the SCC).
  // Note: Removal of the attr from the callsites will happen in
  // InstCombineCalls separately.
  AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
      Attribute::Convergent,
      // Skip non-convergent functions.
      [](const Function &F) { return !F.isConvergent(); },
      // Instructions that break non-convergent assumption.
      [SCCNodes](Instruction &I) {
        return InstrBreaksNonConvergent(I, SCCNodes);
      },
      [](Function &F) {
        LLVM_DEBUG(dbgs() << "Removing convergent attr from fn " << F.getName()
                          << "\n");
        F.setNotConvergent();
      },
      /* RequiresExactDefinition= */ false});
  // Perform all the requested attribute inference actions.
  AI.run(SCCNodes, Changed);
}

/// Infer attributes from all functions in the SCC by scanning every
/// instruction for compliance to the attribute assumptions.
///
/// Returns true if any changes to function attributes were made.
static void inferAttrsFromFunctionBodies(const SCCNodeSet &SCCNodes,
                                         SmallPtrSet<Function *, 8> &Changed) {
  AttributeInferer AI;

  if (!DisableNoUnwindInference)
    // Request to infer nounwind attribute for all the functions in the SCC if
    // every callsite within the SCC is not throwing (except for calls to
    // functions within the SCC). Note that nounwind attribute suffers from
    // derefinement - results may change depending on how functions are
    // optimized. Thus it can be inferred only from exact definitions.
    AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
        Attribute::NoUnwind,
        // Skip non-throwing functions.
        [](const Function &F) { return F.doesNotThrow(); },
        // Instructions that break non-throwing assumption.
        [&SCCNodes](Instruction &I) {
          return InstrBreaksNonThrowing(I, SCCNodes);
        },
        [](Function &F) {
          LLVM_DEBUG(dbgs()
                     << "Adding nounwind attr to fn " << F.getName() << "\n");
          F.setDoesNotThrow();
          ++NumNoUnwind;
        },
        /* RequiresExactDefinition= */ true});

  if (!DisableNoFreeInference)
    // Request to infer nofree attribute for all the functions in the SCC if
    // every callsite within the SCC does not directly or indirectly free
    // memory (except for calls to functions within the SCC). Note that nofree
    // attribute suffers from derefinement - results may change depending on
    // how functions are optimized. Thus it can be inferred only from exact
    // definitions.
    AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
        Attribute::NoFree,
        // Skip functions known not to free memory.
        [](const Function &F) { return F.doesNotFreeMemory(); },
        // Instructions that break non-deallocating assumption.
        [&SCCNodes](Instruction &I) {
          return InstrBreaksNoFree(I, SCCNodes);
        },
        [](Function &F) {
          LLVM_DEBUG(dbgs()
                     << "Adding nofree attr to fn " << F.getName() << "\n");
          F.setDoesNotFreeMemory();
          ++NumNoFree;
        },
        /* RequiresExactDefinition= */ true});

  AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
      Attribute::NoSync,
      // Skip already marked functions.
      [](const Function &F) { return F.hasNoSync(); },
      // Instructions that break nosync assumption.
      [&SCCNodes](Instruction &I) {
        return InstrBreaksNoSync(I, SCCNodes);
      },
      [](Function &F) {
        LLVM_DEBUG(dbgs()
                   << "Adding nosync attr to fn " << F.getName() << "\n");
        F.setNoSync();
        ++NumNoSync;
      },
      /* RequiresExactDefinition= */ true});

  // Perform all the requested attribute inference actions.
  AI.run(SCCNodes, Changed);
}

// Determines if the function 'F' can be marked 'norecurse'.
// It returns true if any call within 'F' could lead to a recursive
// call back to 'F', and false otherwise.
// The 'AnyFunctionsAddressIsTaken' parameter is a module-wide flag
// that is true if any function's address is taken, or if any function
// has external linkage. This is used to determine the safety of
// external/library calls.
static bool mayHaveRecursiveCallee(Function &F,
                                   bool AnyFunctionsAddressIsTaken = true) {
  for (const auto &BB : F) {
    for (const auto &I : BB) {
      if (const auto *CB = dyn_cast<CallBase>(&I)) {
        const Function *Callee = CB->getCalledFunction();
        if (!Callee || Callee == &F)
          return true;

        if (Callee->doesNotRecurse())
          continue;

        if (!AnyFunctionsAddressIsTaken ||
            (Callee->isDeclaration() &&
             Callee->hasFnAttribute(Attribute::NoCallback)))
          continue;
        return true;
      }
    }
  }
  return false;
}

static void addNoRecurseAttrs(const SCCNodeSet &SCCNodes,
                              SmallPtrSet<Function *, 8> &Changed) {
  // Try and identify functions that do not recurse.

  // If the SCC contains multiple nodes we know for sure there is recursion.
  if (SCCNodes.size() != 1)
    return;

  Function *F = *SCCNodes.begin();
  if (!F || !F->hasExactDefinition() || F->doesNotRecurse())
    return;
  if (!mayHaveRecursiveCallee(*F)) {
    // Every call was to a non-recursive function other than this function, and
    // we have no indirect recursion as the SCC size is one. This function
    // cannot recurse.
    F->setDoesNotRecurse();
    ++NumNoRecurse;
    Changed.insert(F);
  }
}

// Set the noreturn function attribute if possible.
static void addNoReturnAttrs(const SCCNodeSet &SCCNodes,
                             SmallPtrSet<Function *, 8> &Changed) {
  for (Function *F : SCCNodes) {
    if (!F || !F->hasExactDefinition() || F->hasFnAttribute(Attribute::Naked) ||
        F->doesNotReturn())
      continue;

    if (!canReturn(*F)) {
      F->setDoesNotReturn();
      Changed.insert(F);
    }
  }
}

static bool allPathsGoThroughCold(Function &F) {
  SmallDenseMap<BasicBlock *, bool, 16> ColdPaths;
  ColdPaths[&F.front()] = false;
  SmallVector<BasicBlock *> Jobs;
  Jobs.push_back(&F.front());

  while (!Jobs.empty()) {
    BasicBlock *BB = Jobs.pop_back_val();

    // If block contains a cold callsite this path through the CG is cold.
    // Ignore whether the instructions actually are guaranteed to transfer
    // execution. Divergent behavior is considered unlikely.
    if (any_of(*BB, [](Instruction &I) {
          if (auto *CB = dyn_cast<CallBase>(&I))
            return CB->hasFnAttr(Attribute::Cold);
          return false;
        })) {
      ColdPaths[BB] = true;
      continue;
    }

    auto Succs = successors(BB);
    // We found a path that doesn't go through any cold callsite.
    if (Succs.empty())
      return false;

    // We didn't find a cold callsite in this BB, so check that all successors
    // contain a cold callsite (or that their successors do).
    // Potential TODO: We could use static branch hints to assume certain
    // successor paths are inherently cold, irrespective of if they contain a
    // cold callsite.
    for (BasicBlock *Succ : Succs) {
      // Start with false, this is necessary to ensure we don't turn loops into
      // cold.
      auto [Iter, Inserted] = ColdPaths.try_emplace(Succ, false);
      if (!Inserted) {
        if (Iter->second)
          continue;
        return false;
      }
      Jobs.push_back(Succ);
    }
  }
  return true;
}

// Set the cold function attribute if possible.
static void addColdAttrs(const SCCNodeSet &SCCNodes,
                         SmallPtrSet<Function *, 8> &Changed) {
  for (Function *F : SCCNodes) {
    if (!F || !F->hasExactDefinition() || F->hasFnAttribute(Attribute::Naked) ||
        F->hasFnAttribute(Attribute::Cold) || F->hasFnAttribute(Attribute::Hot))
      continue;

    // Potential TODO: We could add attribute `cold` on functions with `coldcc`.
    if (allPathsGoThroughCold(*F)) {
      F->addFnAttr(Attribute::Cold);
      ++NumCold;
      Changed.insert(F);
      continue;
    }
  }
}

static bool functionWillReturn(const Function &F) {
  // We can infer and propagate function attributes only when we know that the
  // definition we'll get at link time is *exactly* the definition we see now.
  // For more details, see GlobalValue::mayBeDerefined.
  if (!F.hasExactDefinition())
    return false;

  // Must-progress function without side-effects must return.
  if (F.mustProgress() && F.onlyReadsMemory())
    return true;

  // Can only analyze functions with a definition.
  if (F.isDeclaration())
    return false;

  // Functions with loops require more sophisticated analysis, as the loop
  // may be infinite. For now, don't try to handle them.
  SmallVector<std::pair<const BasicBlock *, const BasicBlock *>> Backedges;
  FindFunctionBackedges(F, Backedges);
  if (!Backedges.empty())
    return false;

  // If there are no loops, then the function is willreturn if all calls in
  // it are willreturn.
  return all_of(instructions(F), [](const Instruction &I) {
    return I.willReturn();
  });
}

// Set the willreturn function attribute if possible.
static void addWillReturn(const SCCNodeSet &SCCNodes,
                          SmallPtrSet<Function *, 8> &Changed) {
  for (Function *F : SCCNodes) {
    if (!F || F->willReturn() || !functionWillReturn(*F))
      continue;

    F->setWillReturn();
    NumWillReturn++;
    Changed.insert(F);
  }
}

static SCCNodesResult createSCCNodeSet(ArrayRef<Function *> Functions) {
  SCCNodesResult Res;
  for (Function *F : Functions) {
    if (!F || F->hasOptNone() || F->hasFnAttribute(Attribute::Naked) ||
        F->isPresplitCoroutine()) {
      // Omit any functions we're trying not to optimize from the set.
      continue;
    }

    Res.SCCNodes.insert(F);
  }
  return Res;
}

template <typename AARGetterT>
static SmallPtrSet<Function *, 8>
deriveAttrsInPostOrder(ArrayRef<Function *> Functions, AARGetterT &&AARGetter,
                       bool ArgAttrsOnly) {
  SCCNodesResult Nodes = createSCCNodeSet(Functions);

  // Bail if the SCC only contains optnone functions.
  if (Nodes.SCCNodes.empty())
    return {};

  SmallPtrSet<Function *, 8> Changed;
  if (ArgAttrsOnly) {
    // ArgAttrsOnly means to only infer attributes that may aid optimizations
    // on the *current* function. "initializes" attribute is to aid
    // optimizations (like DSE) on the callers, so skip "initializes" here.
    addArgumentAttrs(Nodes.SCCNodes, Changed, /*SkipInitializes=*/true);
    return Changed;
  }

  addArgumentReturnedAttrs(Nodes.SCCNodes, Changed);
  addMemoryAttrs(Nodes.SCCNodes, AARGetter, Changed);
  addArgumentAttrs(Nodes.SCCNodes, Changed, /*SkipInitializes=*/false);
  inferConvergent(Nodes.SCCNodes, Changed);
  addNoReturnAttrs(Nodes.SCCNodes, Changed);
  addColdAttrs(Nodes.SCCNodes, Changed);
  addWillReturn(Nodes.SCCNodes, Changed);
  addNoUndefAttrs(Nodes.SCCNodes, Changed);
  addNoAliasAttrs(Nodes.SCCNodes, Changed);
  addNonNullAttrs(Nodes.SCCNodes, Changed);
  inferAttrsFromFunctionBodies(Nodes.SCCNodes, Changed);
  addNoRecurseAttrs(Nodes.SCCNodes, Changed);

  // Finally, infer the maximal set of attributes from the ones we've inferred
  // above.  This is handling the cases where one attribute on a signature
  // implies another, but for implementation reasons the inference rule for
  // the later is missing (or simply less sophisticated).
  for (Function *F : Nodes.SCCNodes)
    if (F)
      if (inferAttributesFromOthers(*F))
        Changed.insert(F);

  return Changed;
}

PreservedAnalyses PostOrderFunctionAttrsPass::run(LazyCallGraph::SCC &C,
                                                  CGSCCAnalysisManager &AM,
                                                  LazyCallGraph &CG,
                                                  CGSCCUpdateResult &) {
  // Skip non-recursive functions if requested.
  // Only infer argument attributes for non-recursive functions, because
  // it can affect optimization behavior in conjunction with noalias.
  bool ArgAttrsOnly = false;
  if (C.size() == 1 && SkipNonRecursive) {
    LazyCallGraph::Node &N = *C.begin();
    if (!N->lookup(N))
      ArgAttrsOnly = true;
  }

  FunctionAnalysisManager &FAM =
      AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();

  // We pass a lambda into functions to wire them up to the analysis manager
  // for getting function analyses.
  auto AARGetter = [&](Function &F) -> AAResults & {
    return FAM.getResult<AAManager>(F);
  };

  SmallVector<Function *, 8> Functions;
  for (LazyCallGraph::Node &N : C) {
    Functions.push_back(&N.getFunction());
  }

  auto ChangedFunctions =
      deriveAttrsInPostOrder(Functions, AARGetter, ArgAttrsOnly);
  if (ChangedFunctions.empty())
    return PreservedAnalyses::all();

  // Invalidate analyses for modified functions so that we don't have to
  // invalidate all analyses for all functions in this SCC.
  PreservedAnalyses FuncPA;
  // We haven't changed the CFG for modified functions.
  FuncPA.preserveSet<CFGAnalyses>();
  for (Function *Changed : ChangedFunctions) {
    FAM.invalidate(*Changed, FuncPA);
    // Also invalidate any direct callers of changed functions since analyses
    // may care about attributes of direct callees. For example, MemorySSA cares
    // about whether or not a call's callee modifies memory and queries that
    // through function attributes.
    for (auto *U : Changed->users()) {
      if (auto *Call = dyn_cast<CallBase>(U)) {
        if (Call->getCalledOperand() == Changed)
          FAM.invalidate(*Call->getFunction(), FuncPA);
      }
    }
  }

  PreservedAnalyses PA;
  // We have not added or removed functions.
  PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
  // We already invalidated all relevant function analyses above.
  PA.preserveSet<AllAnalysesOn<Function>>();
  return PA;
}

void PostOrderFunctionAttrsPass::printPipeline(
    raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
  static_cast<PassInfoMixin<PostOrderFunctionAttrsPass> *>(this)->printPipeline(
      OS, MapClassName2PassName);
  if (SkipNonRecursive)
    OS << "<skip-non-recursive-function-attrs>";
}

static bool addNoRecurseAttrsTopDown(Function &F) {
  if (F.doesNotRecurse())
    return false;

  // We check the preconditions for the function prior to calling this to avoid
  // the cost of building up a reversible post-order list. We assert them here
  // to make sure none of the invariants this relies on were violated.
  assert(!F.isDeclaration() && "Cannot deduce norecurse without a definition!");
  assert(F.hasInternalLinkage() &&
         "Can only do top-down deduction for internal linkage functions!");

  // If F is internal and all of its uses are calls from a non-recursive
  // functions, then none of its calls could in fact recurse without going
  // through a function marked norecurse, and so we can mark this function too
  // as norecurse. Note that the uses must actually be calls -- otherwise
  // a pointer to this function could be returned from a norecurse function but
  // this function could be recursively (indirectly) called. Note that this
  // also detects if F is directly recursive as F is not yet marked as
  // a norecurse function.
  for (auto &U : F.uses()) {
    const CallBase *CB = dyn_cast<CallBase>(U.getUser());
    if (!CB || !CB->isCallee(&U) ||
        !CB->getParent()->getParent()->doesNotRecurse())
      return false;
  }
  F.setDoesNotRecurse();
  ++NumNoRecurse;
  return true;
}

static bool addNoFPClassAttrsTopDown(Function &F) {
  assert(!F.isDeclaration() && "Cannot deduce nofpclass without a definition!");
  unsigned NumArgs = F.arg_size();
  SmallVector<FPClassTest, 8> ArgsNoFPClass(NumArgs, fcAllFlags);
  FPClassTest RetNoFPClass = fcAllFlags;

  bool Changed = false;
  for (User *U : F.users()) {
    auto *CB = dyn_cast<CallBase>(U);
    if (!CB || CB->getCalledFunction() != &F)
      return false;

    RetNoFPClass &= CB->getRetNoFPClass();
    for (unsigned I = 0; I != NumArgs; ++I) {
      // TODO: Consider computeKnownFPClass, at least with a small search
      // depth. This will currently not catch non-splat vectors.
      const APFloat *Cst;
      if (match(CB->getArgOperand(I), m_APFloat(Cst)))
        ArgsNoFPClass[I] &= ~Cst->classify();
      else
        ArgsNoFPClass[I] &= CB->getParamNoFPClass(I);
    }
  }

  LLVMContext &Ctx = F.getContext();

  if (RetNoFPClass != fcNone) {
    FPClassTest OldAttr = F.getAttributes().getRetNoFPClass();
    if (OldAttr != RetNoFPClass) {
      F.addRetAttr(Attribute::getWithNoFPClass(Ctx, RetNoFPClass));
      Changed = true;
    }
  }

  for (unsigned I = 0; I != NumArgs; ++I) {
    FPClassTest ArgNoFPClass = ArgsNoFPClass[I];
    if (ArgNoFPClass == fcNone)
      continue;
    FPClassTest OldAttr = F.getParamNoFPClass(I);
    if (OldAttr == ArgNoFPClass)
      continue;

    F.addParamAttr(I, Attribute::getWithNoFPClass(Ctx, ArgNoFPClass));
    Changed = true;
  }

  return Changed;
}

static bool deduceFunctionAttributeInRPO(Module &M, LazyCallGraph &CG) {
  // We only have a post-order SCC traversal (because SCCs are inherently
  // discovered in post-order), so we accumulate them in a vector and then walk
  // it in reverse. This is simpler than using the RPO iterator infrastructure
  // because we need to combine SCC detection and the PO walk of the call
  // graph. We can also cheat egregiously because we're primarily interested in
  // synthesizing norecurse and so we can only save the singular SCCs as SCCs
  // with multiple functions in them will clearly be recursive.

  SmallVector<Function *, 16> Worklist;
  CG.buildRefSCCs();
  for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs()) {
    for (LazyCallGraph::SCC &SCC : RC) {
      if (SCC.size() != 1)
        continue;
      Function &F = SCC.begin()->getFunction();
      if (!F.isDeclaration() && F.hasInternalLinkage() && !F.use_empty())
        Worklist.push_back(&F);
    }
  }
  bool Changed = false;
  for (auto *F : llvm::reverse(Worklist)) {
    Changed |= addNoRecurseAttrsTopDown(*F);
    Changed |= addNoFPClassAttrsTopDown(*F);
  }

  return Changed;
}

PreservedAnalyses
ReversePostOrderFunctionAttrsPass::run(Module &M, ModuleAnalysisManager &AM) {
  auto &CG = AM.getResult<LazyCallGraphAnalysis>(M);

  if (!deduceFunctionAttributeInRPO(M, CG))
    return PreservedAnalyses::all();

  PreservedAnalyses PA;
  PA.preserve<LazyCallGraphAnalysis>();
  return PA;
}

PreservedAnalyses NoRecurseLTOInferencePass::run(Module &M,
                                                 ModuleAnalysisManager &MAM) {

  // Check if any function in the whole program has its address taken or has
  // potentially external linkage.
  // We use this information when inferring norecurse attribute: If there is
  // no function whose address is taken and all functions have internal
  // linkage, there is no path for a callback to any user function.
  bool AnyFunctionsAddressIsTaken = false;
  for (Function &F : M) {
    if (F.isDeclaration() || F.doesNotRecurse())
      continue;
    if (!F.hasLocalLinkage() || F.hasAddressTaken()) {
      AnyFunctionsAddressIsTaken = true;
      break;
    }
  }

  // Run norecurse inference on all RefSCCs in the LazyCallGraph for this
  // module.
  bool Changed = false;
  LazyCallGraph &CG = MAM.getResult<LazyCallGraphAnalysis>(M);
  CG.buildRefSCCs();

  for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs()) {
    // Skip any RefSCC that is part of a call cycle. A RefSCC containing more
    // than one SCC indicates a recursive relationship involving indirect calls.
    if (RC.size() > 1)
      continue;

    // RefSCC contains a single-SCC. SCC size > 1 indicates mutually recursive
    // functions. Ex: foo1 -> foo2 -> foo3 -> foo1.
    LazyCallGraph::SCC &S = *RC.begin();
    if (S.size() > 1)
      continue;

    // Get the single function from this SCC.
    Function &F = S.begin()->getFunction();
    if (!F.hasExactDefinition() || F.doesNotRecurse())
      continue;

    // If the analysis confirms that this function has no recursive calls
    // (either direct, indirect, or through external linkages),
    // we can safely apply the norecurse attribute.
    if (!mayHaveRecursiveCallee(F, AnyFunctionsAddressIsTaken)) {
      F.setDoesNotRecurse();
      ++NumNoRecurse;
      Changed = true;
    }
  }

  PreservedAnalyses PA;
  if (Changed)
    PA.preserve<LazyCallGraphAnalysis>();
  else
    PA = PreservedAnalyses::all();
  return PA;
}
