//===- 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/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.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());
      }
      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.
      }

    // Only capturing the provenance of the result prevents it from being
    // noalias.
    if (capturesAnything(
            PointerMayBeCaptured(RetVal, CaptureComponents::Provenance)
                .WithoutRet))
      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;
}
