brintos

brintos / llvm-project-archived public Read only

0
0
Text · 507.3 KiB · e806a02 Raw
13806 lines · cpp
1//===- AttributorAttributes.cpp - Attributes for Attributor deduction -----===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// See the Attributor.h file comment and the class descriptions in that file for10// more information.11//12//===----------------------------------------------------------------------===//13 14#include "llvm/Transforms/IPO/Attributor.h"15 16#include "llvm/ADT/APInt.h"17#include "llvm/ADT/ArrayRef.h"18#include "llvm/ADT/DenseMapInfo.h"19#include "llvm/ADT/MapVector.h"20#include "llvm/ADT/SCCIterator.h"21#include "llvm/ADT/STLExtras.h"22#include "llvm/ADT/SetOperations.h"23#include "llvm/ADT/SetVector.h"24#include "llvm/ADT/SmallPtrSet.h"25#include "llvm/ADT/SmallVector.h"26#include "llvm/ADT/Statistic.h"27#include "llvm/ADT/StringExtras.h"28#include "llvm/Analysis/AliasAnalysis.h"29#include "llvm/Analysis/AssumeBundleQueries.h"30#include "llvm/Analysis/AssumptionCache.h"31#include "llvm/Analysis/CaptureTracking.h"32#include "llvm/Analysis/CycleAnalysis.h"33#include "llvm/Analysis/InstructionSimplify.h"34#include "llvm/Analysis/LazyValueInfo.h"35#include "llvm/Analysis/MemoryBuiltins.h"36#include "llvm/Analysis/ScalarEvolution.h"37#include "llvm/Analysis/TargetTransformInfo.h"38#include "llvm/Analysis/ValueTracking.h"39#include "llvm/IR/Argument.h"40#include "llvm/IR/Assumptions.h"41#include "llvm/IR/Attributes.h"42#include "llvm/IR/BasicBlock.h"43#include "llvm/IR/Constant.h"44#include "llvm/IR/Constants.h"45#include "llvm/IR/DataLayout.h"46#include "llvm/IR/DerivedTypes.h"47#include "llvm/IR/GlobalValue.h"48#include "llvm/IR/IRBuilder.h"49#include "llvm/IR/InlineAsm.h"50#include "llvm/IR/InstrTypes.h"51#include "llvm/IR/Instruction.h"52#include "llvm/IR/Instructions.h"53#include "llvm/IR/IntrinsicInst.h"54#include "llvm/IR/IntrinsicsAMDGPU.h"55#include "llvm/IR/IntrinsicsNVPTX.h"56#include "llvm/IR/LLVMContext.h"57#include "llvm/IR/MDBuilder.h"58#include "llvm/IR/NoFolder.h"59#include "llvm/IR/Value.h"60#include "llvm/IR/ValueHandle.h"61#include "llvm/Support/Alignment.h"62#include "llvm/Support/Casting.h"63#include "llvm/Support/CommandLine.h"64#include "llvm/Support/ErrorHandling.h"65#include "llvm/Support/GraphWriter.h"66#include "llvm/Support/InterleavedRange.h"67#include "llvm/Support/KnownFPClass.h"68#include "llvm/Support/MathExtras.h"69#include "llvm/Support/TypeSize.h"70#include "llvm/Support/raw_ostream.h"71#include "llvm/Transforms/Utils/BasicBlockUtils.h"72#include "llvm/Transforms/Utils/CallPromotionUtils.h"73#include "llvm/Transforms/Utils/Local.h"74#include "llvm/Transforms/Utils/ValueMapper.h"75#include <cassert>76#include <numeric>77#include <optional>78#include <string>79 80using namespace llvm;81 82#define DEBUG_TYPE "attributor"83 84static cl::opt<bool> ManifestInternal(85    "attributor-manifest-internal", cl::Hidden,86    cl::desc("Manifest Attributor internal string attributes."),87    cl::init(false));88 89static cl::opt<int> MaxHeapToStackSize("max-heap-to-stack-size", cl::init(128),90                                       cl::Hidden);91 92template <>93unsigned llvm::PotentialConstantIntValuesState::MaxPotentialValues = 0;94 95template <> unsigned llvm::PotentialLLVMValuesState::MaxPotentialValues = -1;96 97static cl::opt<unsigned, true> MaxPotentialValues(98    "attributor-max-potential-values", cl::Hidden,99    cl::desc("Maximum number of potential values to be "100             "tracked for each position."),101    cl::location(llvm::PotentialConstantIntValuesState::MaxPotentialValues),102    cl::init(7));103 104static cl::opt<int> MaxPotentialValuesIterations(105    "attributor-max-potential-values-iterations", cl::Hidden,106    cl::desc(107        "Maximum number of iterations we keep dismantling potential values."),108    cl::init(64));109 110STATISTIC(NumAAs, "Number of abstract attributes created");111STATISTIC(NumIndirectCallsPromoted, "Number of indirect calls promoted");112 113// Some helper macros to deal with statistics tracking.114//115// Usage:116// For simple IR attribute tracking overload trackStatistics in the abstract117// attribute and choose the right STATS_DECLTRACK_********* macro,118// e.g.,:119//  void trackStatistics() const override {120//    STATS_DECLTRACK_ARG_ATTR(returned)121//  }122// If there is a single "increment" side one can use the macro123// STATS_DECLTRACK with a custom message. If there are multiple increment124// sides, STATS_DECL and STATS_TRACK can also be used separately.125//126#define BUILD_STAT_MSG_IR_ATTR(TYPE, NAME)                                     \127  ("Number of " #TYPE " marked '" #NAME "'")128#define BUILD_STAT_NAME(NAME, TYPE) NumIR##TYPE##_##NAME129#define STATS_DECL_(NAME, MSG) STATISTIC(NAME, MSG);130#define STATS_DECL(NAME, TYPE, MSG)                                            \131  STATS_DECL_(BUILD_STAT_NAME(NAME, TYPE), MSG);132#define STATS_TRACK(NAME, TYPE) ++(BUILD_STAT_NAME(NAME, TYPE));133#define STATS_DECLTRACK(NAME, TYPE, MSG)                                       \134  {STATS_DECL(NAME, TYPE, MSG) STATS_TRACK(NAME, TYPE)}135#define STATS_DECLTRACK_ARG_ATTR(NAME)                                         \136  STATS_DECLTRACK(NAME, Arguments, BUILD_STAT_MSG_IR_ATTR(arguments, NAME))137#define STATS_DECLTRACK_CSARG_ATTR(NAME)                                       \138  STATS_DECLTRACK(NAME, CSArguments,                                           \139                  BUILD_STAT_MSG_IR_ATTR(call site arguments, NAME))140#define STATS_DECLTRACK_FN_ATTR(NAME)                                          \141  STATS_DECLTRACK(NAME, Function, BUILD_STAT_MSG_IR_ATTR(functions, NAME))142#define STATS_DECLTRACK_CS_ATTR(NAME)                                          \143  STATS_DECLTRACK(NAME, CS, BUILD_STAT_MSG_IR_ATTR(call site, NAME))144#define STATS_DECLTRACK_FNRET_ATTR(NAME)                                       \145  STATS_DECLTRACK(NAME, FunctionReturn,                                        \146                  BUILD_STAT_MSG_IR_ATTR(function returns, NAME))147#define STATS_DECLTRACK_CSRET_ATTR(NAME)                                       \148  STATS_DECLTRACK(NAME, CSReturn,                                              \149                  BUILD_STAT_MSG_IR_ATTR(call site returns, NAME))150#define STATS_DECLTRACK_FLOATING_ATTR(NAME)                                    \151  STATS_DECLTRACK(NAME, Floating,                                              \152                  ("Number of floating values known to be '" #NAME "'"))153 154// Specialization of the operator<< for abstract attributes subclasses. This155// disambiguates situations where multiple operators are applicable.156namespace llvm {157#define PIPE_OPERATOR(CLASS)                                                   \158  raw_ostream &operator<<(raw_ostream &OS, const CLASS &AA) {                  \159    return OS << static_cast<const AbstractAttribute &>(AA);                   \160  }161 162PIPE_OPERATOR(AAIsDead)163PIPE_OPERATOR(AANoUnwind)164PIPE_OPERATOR(AANoSync)165PIPE_OPERATOR(AANoRecurse)166PIPE_OPERATOR(AANonConvergent)167PIPE_OPERATOR(AAWillReturn)168PIPE_OPERATOR(AANoReturn)169PIPE_OPERATOR(AANonNull)170PIPE_OPERATOR(AAMustProgress)171PIPE_OPERATOR(AANoAlias)172PIPE_OPERATOR(AADereferenceable)173PIPE_OPERATOR(AAAlign)174PIPE_OPERATOR(AAInstanceInfo)175PIPE_OPERATOR(AANoCapture)176PIPE_OPERATOR(AAValueSimplify)177PIPE_OPERATOR(AANoFree)178PIPE_OPERATOR(AAHeapToStack)179PIPE_OPERATOR(AAIntraFnReachability)180PIPE_OPERATOR(AAMemoryBehavior)181PIPE_OPERATOR(AAMemoryLocation)182PIPE_OPERATOR(AAValueConstantRange)183PIPE_OPERATOR(AAPrivatizablePtr)184PIPE_OPERATOR(AAUndefinedBehavior)185PIPE_OPERATOR(AAPotentialConstantValues)186PIPE_OPERATOR(AAPotentialValues)187PIPE_OPERATOR(AANoUndef)188PIPE_OPERATOR(AANoFPClass)189PIPE_OPERATOR(AACallEdges)190PIPE_OPERATOR(AAInterFnReachability)191PIPE_OPERATOR(AAPointerInfo)192PIPE_OPERATOR(AAAssumptionInfo)193PIPE_OPERATOR(AAUnderlyingObjects)194PIPE_OPERATOR(AAInvariantLoadPointer)195PIPE_OPERATOR(AAAddressSpace)196PIPE_OPERATOR(AANoAliasAddrSpace)197PIPE_OPERATOR(AAAllocationInfo)198PIPE_OPERATOR(AAIndirectCallInfo)199PIPE_OPERATOR(AAGlobalValueInfo)200PIPE_OPERATOR(AADenormalFPMath)201 202#undef PIPE_OPERATOR203 204template <>205ChangeStatus clampStateAndIndicateChange<DerefState>(DerefState &S,206                                                     const DerefState &R) {207  ChangeStatus CS0 =208      clampStateAndIndicateChange(S.DerefBytesState, R.DerefBytesState);209  ChangeStatus CS1 = clampStateAndIndicateChange(S.GlobalState, R.GlobalState);210  return CS0 | CS1;211}212 213} // namespace llvm214 215static bool mayBeInCycle(const CycleInfo *CI, const Instruction *I,216                         bool HeaderOnly, Cycle **CPtr = nullptr) {217  if (!CI)218    return true;219  auto *BB = I->getParent();220  auto *C = CI->getCycle(BB);221  if (!C)222    return false;223  if (CPtr)224    *CPtr = C;225  return !HeaderOnly || BB == C->getHeader();226}227 228/// Checks if a type could have padding bytes.229static bool isDenselyPacked(Type *Ty, const DataLayout &DL) {230  // There is no size information, so be conservative.231  if (!Ty->isSized())232    return false;233 234  // If the alloc size is not equal to the storage size, then there are padding235  // bytes. For x86_fp80 on x86-64, size: 80 alloc size: 128.236  if (DL.getTypeSizeInBits(Ty) != DL.getTypeAllocSizeInBits(Ty))237    return false;238 239  // FIXME: This isn't the right way to check for padding in vectors with240  // non-byte-size elements.241  if (VectorType *SeqTy = dyn_cast<VectorType>(Ty))242    return isDenselyPacked(SeqTy->getElementType(), DL);243 244  // For array types, check for padding within members.245  if (ArrayType *SeqTy = dyn_cast<ArrayType>(Ty))246    return isDenselyPacked(SeqTy->getElementType(), DL);247 248  if (!isa<StructType>(Ty))249    return true;250 251  // Check for padding within and between elements of a struct.252  StructType *StructTy = cast<StructType>(Ty);253  const StructLayout *Layout = DL.getStructLayout(StructTy);254  uint64_t StartPos = 0;255  for (unsigned I = 0, E = StructTy->getNumElements(); I < E; ++I) {256    Type *ElTy = StructTy->getElementType(I);257    if (!isDenselyPacked(ElTy, DL))258      return false;259    if (StartPos != Layout->getElementOffsetInBits(I))260      return false;261    StartPos += DL.getTypeAllocSizeInBits(ElTy);262  }263 264  return true;265}266 267/// Get pointer operand of memory accessing instruction. If \p I is268/// not a memory accessing instruction, return nullptr. If \p AllowVolatile,269/// is set to false and the instruction is volatile, return nullptr.270static const Value *getPointerOperand(const Instruction *I,271                                      bool AllowVolatile) {272  if (!AllowVolatile && I->isVolatile())273    return nullptr;274 275  if (auto *LI = dyn_cast<LoadInst>(I)) {276    return LI->getPointerOperand();277  }278 279  if (auto *SI = dyn_cast<StoreInst>(I)) {280    return SI->getPointerOperand();281  }282 283  if (auto *CXI = dyn_cast<AtomicCmpXchgInst>(I)) {284    return CXI->getPointerOperand();285  }286 287  if (auto *RMWI = dyn_cast<AtomicRMWInst>(I)) {288    return RMWI->getPointerOperand();289  }290 291  return nullptr;292}293 294/// Helper function to create a pointer based on \p Ptr, and advanced by \p295/// Offset bytes.296static Value *constructPointer(Value *Ptr, int64_t Offset,297                               IRBuilder<NoFolder> &IRB) {298  LLVM_DEBUG(dbgs() << "Construct pointer: " << *Ptr << " + " << Offset299                    << "-bytes\n");300 301  if (Offset)302    Ptr = IRB.CreatePtrAdd(Ptr, IRB.getInt64(Offset),303                           Ptr->getName() + ".b" + Twine(Offset));304  return Ptr;305}306 307static const Value *308stripAndAccumulateOffsets(Attributor &A, const AbstractAttribute &QueryingAA,309                          const Value *Val, const DataLayout &DL, APInt &Offset,310                          bool GetMinOffset, bool AllowNonInbounds,311                          bool UseAssumed = false) {312 313  auto AttributorAnalysis = [&](Value &V, APInt &ROffset) -> bool {314    const IRPosition &Pos = IRPosition::value(V);315    // Only track dependence if we are going to use the assumed info.316    const AAValueConstantRange *ValueConstantRangeAA =317        A.getAAFor<AAValueConstantRange>(QueryingAA, Pos,318                                         UseAssumed ? DepClassTy::OPTIONAL319                                                    : DepClassTy::NONE);320    if (!ValueConstantRangeAA)321      return false;322    ConstantRange Range = UseAssumed ? ValueConstantRangeAA->getAssumed()323                                     : ValueConstantRangeAA->getKnown();324    if (Range.isFullSet())325      return false;326 327    // We can only use the lower part of the range because the upper part can328    // be higher than what the value can really be.329    if (GetMinOffset)330      ROffset = Range.getSignedMin();331    else332      ROffset = Range.getSignedMax();333    return true;334  };335 336  return Val->stripAndAccumulateConstantOffsets(DL, Offset, AllowNonInbounds,337                                                /* AllowInvariant */ true,338                                                AttributorAnalysis);339}340 341static const Value *342getMinimalBaseOfPointer(Attributor &A, const AbstractAttribute &QueryingAA,343                        const Value *Ptr, int64_t &BytesOffset,344                        const DataLayout &DL, bool AllowNonInbounds = false) {345  APInt OffsetAPInt(DL.getIndexTypeSizeInBits(Ptr->getType()), 0);346  const Value *Base =347      stripAndAccumulateOffsets(A, QueryingAA, Ptr, DL, OffsetAPInt,348                                /* GetMinOffset */ true, AllowNonInbounds);349 350  BytesOffset = OffsetAPInt.getSExtValue();351  return Base;352}353 354/// Clamp the information known for all returned values of a function355/// (identified by \p QueryingAA) into \p S.356template <typename AAType, typename StateType = typename AAType::StateType,357          Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind,358          bool RecurseForSelectAndPHI = true>359static void clampReturnedValueStates(360    Attributor &A, const AAType &QueryingAA, StateType &S,361    const IRPosition::CallBaseContext *CBContext = nullptr) {362  LLVM_DEBUG(dbgs() << "[Attributor] Clamp return value states for "363                    << QueryingAA << " into " << S << "\n");364 365  assert((QueryingAA.getIRPosition().getPositionKind() ==366              IRPosition::IRP_RETURNED ||367          QueryingAA.getIRPosition().getPositionKind() ==368              IRPosition::IRP_CALL_SITE_RETURNED) &&369         "Can only clamp returned value states for a function returned or call "370         "site returned position!");371 372  // Use an optional state as there might not be any return values and we want373  // to join (IntegerState::operator&) the state of all there are.374  std::optional<StateType> T;375 376  // Callback for each possibly returned value.377  auto CheckReturnValue = [&](Value &RV) -> bool {378    const IRPosition &RVPos = IRPosition::value(RV, CBContext);379    // If possible, use the hasAssumedIRAttr interface.380    if (Attribute::isEnumAttrKind(IRAttributeKind)) {381      bool IsKnown;382      return AA::hasAssumedIRAttr<IRAttributeKind>(383          A, &QueryingAA, RVPos, DepClassTy::REQUIRED, IsKnown);384    }385 386    const AAType *AA =387        A.getAAFor<AAType>(QueryingAA, RVPos, DepClassTy::REQUIRED);388    if (!AA)389      return false;390    LLVM_DEBUG(dbgs() << "[Attributor] RV: " << RV391                      << " AA: " << AA->getAsStr(&A) << " @ " << RVPos << "\n");392    const StateType &AAS = AA->getState();393    if (!T)394      T = StateType::getBestState(AAS);395    *T &= AAS;396    LLVM_DEBUG(dbgs() << "[Attributor] AA State: " << AAS << " RV State: " << T397                      << "\n");398    return T->isValidState();399  };400 401  if (!A.checkForAllReturnedValues(CheckReturnValue, QueryingAA,402                                   AA::ValueScope::Intraprocedural,403                                   RecurseForSelectAndPHI))404    S.indicatePessimisticFixpoint();405  else if (T)406    S ^= *T;407}408 409namespace {410/// Helper class for generic deduction: return value -> returned position.411template <typename AAType, typename BaseType,412          typename StateType = typename BaseType::StateType,413          bool PropagateCallBaseContext = false,414          Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind,415          bool RecurseForSelectAndPHI = true>416struct AAReturnedFromReturnedValues : public BaseType {417  AAReturnedFromReturnedValues(const IRPosition &IRP, Attributor &A)418      : BaseType(IRP, A) {}419 420  /// See AbstractAttribute::updateImpl(...).421  ChangeStatus updateImpl(Attributor &A) override {422    StateType S(StateType::getBestState(this->getState()));423    clampReturnedValueStates<AAType, StateType, IRAttributeKind,424                             RecurseForSelectAndPHI>(425        A, *this, S,426        PropagateCallBaseContext ? this->getCallBaseContext() : nullptr);427    // TODO: If we know we visited all returned values, thus no are assumed428    // dead, we can take the known information from the state T.429    return clampStateAndIndicateChange<StateType>(this->getState(), S);430  }431};432 433/// Clamp the information known at all call sites for a given argument434/// (identified by \p QueryingAA) into \p S.435template <typename AAType, typename StateType = typename AAType::StateType,436          Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>437static void clampCallSiteArgumentStates(Attributor &A, const AAType &QueryingAA,438                                        StateType &S) {439  LLVM_DEBUG(dbgs() << "[Attributor] Clamp call site argument states for "440                    << QueryingAA << " into " << S << "\n");441 442  assert(QueryingAA.getIRPosition().getPositionKind() ==443             IRPosition::IRP_ARGUMENT &&444         "Can only clamp call site argument states for an argument position!");445 446  // Use an optional state as there might not be any return values and we want447  // to join (IntegerState::operator&) the state of all there are.448  std::optional<StateType> T;449 450  // The argument number which is also the call site argument number.451  unsigned ArgNo = QueryingAA.getIRPosition().getCallSiteArgNo();452 453  auto CallSiteCheck = [&](AbstractCallSite ACS) {454    const IRPosition &ACSArgPos = IRPosition::callsite_argument(ACS, ArgNo);455    // Check if a coresponding argument was found or if it is on not associated456    // (which can happen for callback calls).457    if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)458      return false;459 460    // If possible, use the hasAssumedIRAttr interface.461    if (Attribute::isEnumAttrKind(IRAttributeKind)) {462      bool IsKnown;463      return AA::hasAssumedIRAttr<IRAttributeKind>(464          A, &QueryingAA, ACSArgPos, DepClassTy::REQUIRED, IsKnown);465    }466 467    const AAType *AA =468        A.getAAFor<AAType>(QueryingAA, ACSArgPos, DepClassTy::REQUIRED);469    if (!AA)470      return false;471    LLVM_DEBUG(dbgs() << "[Attributor] ACS: " << *ACS.getInstruction()472                      << " AA: " << AA->getAsStr(&A) << " @" << ACSArgPos473                      << "\n");474    const StateType &AAS = AA->getState();475    if (!T)476      T = StateType::getBestState(AAS);477    *T &= AAS;478    LLVM_DEBUG(dbgs() << "[Attributor] AA State: " << AAS << " CSA State: " << T479                      << "\n");480    return T->isValidState();481  };482 483  bool UsedAssumedInformation = false;484  if (!A.checkForAllCallSites(CallSiteCheck, QueryingAA, true,485                              UsedAssumedInformation))486    S.indicatePessimisticFixpoint();487  else if (T)488    S ^= *T;489}490 491/// This function is the bridge between argument position and the call base492/// context.493template <typename AAType, typename BaseType,494          typename StateType = typename AAType::StateType,495          Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>496bool getArgumentStateFromCallBaseContext(Attributor &A,497                                         BaseType &QueryingAttribute,498                                         IRPosition &Pos, StateType &State) {499  assert((Pos.getPositionKind() == IRPosition::IRP_ARGUMENT) &&500         "Expected an 'argument' position !");501  const CallBase *CBContext = Pos.getCallBaseContext();502  if (!CBContext)503    return false;504 505  int ArgNo = Pos.getCallSiteArgNo();506  assert(ArgNo >= 0 && "Invalid Arg No!");507  const IRPosition CBArgPos = IRPosition::callsite_argument(*CBContext, ArgNo);508 509  // If possible, use the hasAssumedIRAttr interface.510  if (Attribute::isEnumAttrKind(IRAttributeKind)) {511    bool IsKnown;512    return AA::hasAssumedIRAttr<IRAttributeKind>(513        A, &QueryingAttribute, CBArgPos, DepClassTy::REQUIRED, IsKnown);514  }515 516  const auto *AA =517      A.getAAFor<AAType>(QueryingAttribute, CBArgPos, DepClassTy::REQUIRED);518  if (!AA)519    return false;520  const StateType &CBArgumentState =521      static_cast<const StateType &>(AA->getState());522 523  LLVM_DEBUG(dbgs() << "[Attributor] Briding Call site context to argument"524                    << "Position:" << Pos << "CB Arg state:" << CBArgumentState525                    << "\n");526 527  // NOTE: If we want to do call site grouping it should happen here.528  State ^= CBArgumentState;529  return true;530}531 532/// Helper class for generic deduction: call site argument -> argument position.533template <typename AAType, typename BaseType,534          typename StateType = typename AAType::StateType,535          bool BridgeCallBaseContext = false,536          Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>537struct AAArgumentFromCallSiteArguments : public BaseType {538  AAArgumentFromCallSiteArguments(const IRPosition &IRP, Attributor &A)539      : BaseType(IRP, A) {}540 541  /// See AbstractAttribute::updateImpl(...).542  ChangeStatus updateImpl(Attributor &A) override {543    StateType S = StateType::getBestState(this->getState());544 545    if (BridgeCallBaseContext) {546      bool Success =547          getArgumentStateFromCallBaseContext<AAType, BaseType, StateType,548                                              IRAttributeKind>(549              A, *this, this->getIRPosition(), S);550      if (Success)551        return clampStateAndIndicateChange<StateType>(this->getState(), S);552    }553    clampCallSiteArgumentStates<AAType, StateType, IRAttributeKind>(A, *this,554                                                                    S);555 556    // TODO: If we know we visited all incoming values, thus no are assumed557    // dead, we can take the known information from the state T.558    return clampStateAndIndicateChange<StateType>(this->getState(), S);559  }560};561 562/// Helper class for generic replication: function returned -> cs returned.563template <typename AAType, typename BaseType,564          typename StateType = typename BaseType::StateType,565          bool IntroduceCallBaseContext = false,566          Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>567struct AACalleeToCallSite : public BaseType {568  AACalleeToCallSite(const IRPosition &IRP, Attributor &A) : BaseType(IRP, A) {}569 570  /// See AbstractAttribute::updateImpl(...).571  ChangeStatus updateImpl(Attributor &A) override {572    auto IRPKind = this->getIRPosition().getPositionKind();573    assert((IRPKind == IRPosition::IRP_CALL_SITE_RETURNED ||574            IRPKind == IRPosition::IRP_CALL_SITE) &&575           "Can only wrap function returned positions for call site "576           "returned positions!");577    auto &S = this->getState();578 579    CallBase &CB = cast<CallBase>(this->getAnchorValue());580    if (IntroduceCallBaseContext)581      LLVM_DEBUG(dbgs() << "[Attributor] Introducing call base context:" << CB582                        << "\n");583 584    ChangeStatus Changed = ChangeStatus::UNCHANGED;585    auto CalleePred = [&](ArrayRef<const Function *> Callees) {586      for (const Function *Callee : Callees) {587        IRPosition FnPos =588            IRPKind == llvm::IRPosition::IRP_CALL_SITE_RETURNED589                ? IRPosition::returned(*Callee,590                                       IntroduceCallBaseContext ? &CB : nullptr)591                : IRPosition::function(592                      *Callee, IntroduceCallBaseContext ? &CB : nullptr);593        // If possible, use the hasAssumedIRAttr interface.594        if (Attribute::isEnumAttrKind(IRAttributeKind)) {595          bool IsKnown;596          if (!AA::hasAssumedIRAttr<IRAttributeKind>(597                  A, this, FnPos, DepClassTy::REQUIRED, IsKnown))598            return false;599          continue;600        }601 602        const AAType *AA =603            A.getAAFor<AAType>(*this, FnPos, DepClassTy::REQUIRED);604        if (!AA)605          return false;606        Changed |= clampStateAndIndicateChange(S, AA->getState());607        if (S.isAtFixpoint())608          return S.isValidState();609      }610      return true;611    };612    if (!A.checkForAllCallees(CalleePred, *this, CB))613      return S.indicatePessimisticFixpoint();614    return Changed;615  }616};617 618/// Helper function to accumulate uses.619template <class AAType, typename StateType = typename AAType::StateType>620static void followUsesInContext(AAType &AA, Attributor &A,621                                MustBeExecutedContextExplorer &Explorer,622                                const Instruction *CtxI,623                                SetVector<const Use *> &Uses,624                                StateType &State) {625  auto EIt = Explorer.begin(CtxI), EEnd = Explorer.end(CtxI);626  for (unsigned u = 0; u < Uses.size(); ++u) {627    const Use *U = Uses[u];628    if (const Instruction *UserI = dyn_cast<Instruction>(U->getUser())) {629      bool Found = Explorer.findInContextOf(UserI, EIt, EEnd);630      if (Found && AA.followUseInMBEC(A, U, UserI, State))631        Uses.insert_range(llvm::make_pointer_range(UserI->uses()));632    }633  }634}635 636/// Use the must-be-executed-context around \p I to add information into \p S.637/// The AAType class is required to have `followUseInMBEC` method with the638/// following signature and behaviour:639///640/// bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I)641/// U - Underlying use.642/// I - The user of the \p U.643/// Returns true if the value should be tracked transitively.644///645template <class AAType, typename StateType = typename AAType::StateType>646static void followUsesInMBEC(AAType &AA, Attributor &A, StateType &S,647                             Instruction &CtxI) {648  const Value &Val = AA.getIRPosition().getAssociatedValue();649  if (isa<ConstantData>(Val))650    return;651 652  MustBeExecutedContextExplorer *Explorer =653      A.getInfoCache().getMustBeExecutedContextExplorer();654  if (!Explorer)655    return;656 657  // Container for (transitive) uses of the associated value.658  SetVector<const Use *> Uses;659  for (const Use &U : Val.uses())660    Uses.insert(&U);661 662  followUsesInContext<AAType>(AA, A, *Explorer, &CtxI, Uses, S);663 664  if (S.isAtFixpoint())665    return;666 667  SmallVector<const BranchInst *, 4> BrInsts;668  SmallPtrSet<const Instruction *, 16> Visited;669  auto Pred = [&](const Instruction *I) {670    if (!Visited.insert(I).second)671      return false;672    if (const BranchInst *Br = dyn_cast<BranchInst>(I))673      if (Br->isConditional())674        BrInsts.push_back(Br);675    return true;676  };677 678  // Here, accumulate conditional branch instructions in the context. We679  // explore the child paths and collect the known states. The disjunction of680  // those states can be merged to its own state. Let ParentState_i be a state681  // to indicate the known information for an i-th branch instruction in the682  // context. ChildStates are created for its successors respectively.683  //684  // ParentS_1 = ChildS_{1, 1} /\ ChildS_{1, 2} /\ ... /\ ChildS_{1, n_1}685  // ParentS_2 = ChildS_{2, 1} /\ ChildS_{2, 2} /\ ... /\ ChildS_{2, n_2}686  //      ...687  // ParentS_m = ChildS_{m, 1} /\ ChildS_{m, 2} /\ ... /\ ChildS_{m, n_m}688  //689  // Known State |= ParentS_1 \/ ParentS_2 \/... \/ ParentS_m690 691  Explorer->checkForAllContext(&CtxI, Pred);692  while (!BrInsts.empty()) {693    const BranchInst *Br = BrInsts.pop_back_val();694    StateType ParentState;695 696    // The known state of the parent state is a conjunction of children's697    // known states so it is initialized with a best state.698    ParentState.indicateOptimisticFixpoint();699 700    for (const BasicBlock *BB : Br->successors()) {701      StateType ChildState;702      size_t BeforeSize = Uses.size();703      const Instruction *I = &BB->front();704      followUsesInContext(AA, A, *Explorer, I, Uses, ChildState);705 706      // Erase uses which only appear in the child.707      for (auto It = Uses.begin() + BeforeSize; It != Uses.end();)708        It = Uses.erase(It);709 710      ParentState &= ChildState;711 712      // Check for recursive conditional branches.713      Explorer->checkForAllContext(I, Pred);714    }715 716    // Use only known state.717    S += ParentState;718  }719}720} // namespace721 722/// ------------------------ PointerInfo ---------------------------------------723 724namespace llvm {725namespace AA {726namespace PointerInfo {727 728struct State;729 730} // namespace PointerInfo731} // namespace AA732 733/// Helper for AA::PointerInfo::Access DenseMap/Set usage.734template <>735struct DenseMapInfo<AAPointerInfo::Access> : DenseMapInfo<Instruction *> {736  using Access = AAPointerInfo::Access;737  static inline Access getEmptyKey();738  static inline Access getTombstoneKey();739  static unsigned getHashValue(const Access &A);740  static bool isEqual(const Access &LHS, const Access &RHS);741};742 743/// Helper that allows RangeTy as a key in a DenseMap.744template <> struct DenseMapInfo<AA::RangeTy> {745  static inline AA::RangeTy getEmptyKey() {746    auto EmptyKey = DenseMapInfo<int64_t>::getEmptyKey();747    return AA::RangeTy{EmptyKey, EmptyKey};748  }749 750  static inline AA::RangeTy getTombstoneKey() {751    auto TombstoneKey = DenseMapInfo<int64_t>::getTombstoneKey();752    return AA::RangeTy{TombstoneKey, TombstoneKey};753  }754 755  static unsigned getHashValue(const AA::RangeTy &Range) {756    return detail::combineHashValue(757        DenseMapInfo<int64_t>::getHashValue(Range.Offset),758        DenseMapInfo<int64_t>::getHashValue(Range.Size));759  }760 761  static bool isEqual(const AA::RangeTy &A, const AA::RangeTy B) {762    return A == B;763  }764};765 766/// Helper for AA::PointerInfo::Access DenseMap/Set usage ignoring everythign767/// but the instruction768struct AccessAsInstructionInfo : DenseMapInfo<Instruction *> {769  using Base = DenseMapInfo<Instruction *>;770  using Access = AAPointerInfo::Access;771  static inline Access getEmptyKey();772  static inline Access getTombstoneKey();773  static unsigned getHashValue(const Access &A);774  static bool isEqual(const Access &LHS, const Access &RHS);775};776 777} // namespace llvm778 779/// A type to track pointer/struct usage and accesses for AAPointerInfo.780struct AA::PointerInfo::State : public AbstractState {781  /// Return the best possible representable state.782  static State getBestState(const State &SIS) { return State(); }783 784  /// Return the worst possible representable state.785  static State getWorstState(const State &SIS) {786    State R;787    R.indicatePessimisticFixpoint();788    return R;789  }790 791  State() = default;792  State(State &&SIS) = default;793 794  const State &getAssumed() const { return *this; }795 796  /// See AbstractState::isValidState().797  bool isValidState() const override { return BS.isValidState(); }798 799  /// See AbstractState::isAtFixpoint().800  bool isAtFixpoint() const override { return BS.isAtFixpoint(); }801 802  /// See AbstractState::indicateOptimisticFixpoint().803  ChangeStatus indicateOptimisticFixpoint() override {804    BS.indicateOptimisticFixpoint();805    return ChangeStatus::UNCHANGED;806  }807 808  /// See AbstractState::indicatePessimisticFixpoint().809  ChangeStatus indicatePessimisticFixpoint() override {810    BS.indicatePessimisticFixpoint();811    return ChangeStatus::CHANGED;812  }813 814  State &operator=(const State &R) {815    if (this == &R)816      return *this;817    BS = R.BS;818    AccessList = R.AccessList;819    OffsetBins = R.OffsetBins;820    RemoteIMap = R.RemoteIMap;821    ReturnedOffsets = R.ReturnedOffsets;822    return *this;823  }824 825  State &operator=(State &&R) {826    if (this == &R)827      return *this;828    std::swap(BS, R.BS);829    std::swap(AccessList, R.AccessList);830    std::swap(OffsetBins, R.OffsetBins);831    std::swap(RemoteIMap, R.RemoteIMap);832    std::swap(ReturnedOffsets, R.ReturnedOffsets);833    return *this;834  }835 836  /// Add a new Access to the state at offset \p Offset and with size \p Size.837  /// The access is associated with \p I, writes \p Content (if anything), and838  /// is of kind \p Kind. If an Access already exists for the same \p I and same839  /// \p RemoteI, the two are combined, potentially losing information about840  /// offset and size. The resulting access must now be moved from its original841  /// OffsetBin to the bin for its new offset.842  ///843  /// \Returns CHANGED, if the state changed, UNCHANGED otherwise.844  ChangeStatus addAccess(Attributor &A, const AAPointerInfo::RangeList &Ranges,845                         Instruction &I, std::optional<Value *> Content,846                         AAPointerInfo::AccessKind Kind, Type *Ty,847                         Instruction *RemoteI = nullptr);848 849  AAPointerInfo::const_bin_iterator begin() const { return OffsetBins.begin(); }850  AAPointerInfo::const_bin_iterator end() const { return OffsetBins.end(); }851  int64_t numOffsetBins() const { return OffsetBins.size(); }852 853  const AAPointerInfo::Access &getAccess(unsigned Index) const {854    return AccessList[Index];855  }856 857protected:858  // Every memory instruction results in an Access object. We maintain a list of859  // all Access objects that we own, along with the following maps:860  //861  // - OffsetBins: RangeTy -> { Access }862  // - RemoteIMap: RemoteI x LocalI -> Access863  //864  // A RemoteI is any instruction that accesses memory. RemoteI is different865  // from LocalI if and only if LocalI is a call; then RemoteI is some866  // instruction in the callgraph starting from LocalI. Multiple paths in the867  // callgraph from LocalI to RemoteI may produce multiple accesses, but these868  // are all combined into a single Access object. This may result in loss of869  // information in RangeTy in the Access object.870  SmallVector<AAPointerInfo::Access> AccessList;871  AAPointerInfo::OffsetBinsTy OffsetBins;872  DenseMap<const Instruction *, SmallVector<unsigned>> RemoteIMap;873 874  /// Flag to determine if the underlying pointer is reaching a return statement875  /// in the associated function or not. Returns in other functions cause876  /// invalidation.877  AAPointerInfo::OffsetInfo ReturnedOffsets;878 879  /// See AAPointerInfo::forallInterferingAccesses.880  template <typename F>881  bool forallInterferingAccesses(AA::RangeTy Range, F CB) const {882    if (!isValidState() || !ReturnedOffsets.isUnassigned())883      return false;884 885    for (const auto &It : OffsetBins) {886      AA::RangeTy ItRange = It.getFirst();887      if (!Range.mayOverlap(ItRange))888        continue;889      bool IsExact = Range == ItRange && !Range.offsetOrSizeAreUnknown();890      for (auto Index : It.getSecond()) {891        auto &Access = AccessList[Index];892        if (!CB(Access, IsExact))893          return false;894      }895    }896    return true;897  }898 899  /// See AAPointerInfo::forallInterferingAccesses.900  template <typename F>901  bool forallInterferingAccesses(Instruction &I, F CB,902                                 AA::RangeTy &Range) const {903    if (!isValidState() || !ReturnedOffsets.isUnassigned())904      return false;905 906    auto LocalList = RemoteIMap.find(&I);907    if (LocalList == RemoteIMap.end()) {908      return true;909    }910 911    for (unsigned Index : LocalList->getSecond()) {912      for (auto &R : AccessList[Index]) {913        Range &= R;914        if (Range.offsetAndSizeAreUnknown())915          break;916      }917    }918    return forallInterferingAccesses(Range, CB);919  }920 921private:922  /// State to track fixpoint and validity.923  BooleanState BS;924};925 926ChangeStatus AA::PointerInfo::State::addAccess(927    Attributor &A, const AAPointerInfo::RangeList &Ranges, Instruction &I,928    std::optional<Value *> Content, AAPointerInfo::AccessKind Kind, Type *Ty,929    Instruction *RemoteI) {930  RemoteI = RemoteI ? RemoteI : &I;931 932  // Check if we have an access for this instruction, if not, simply add it.933  auto &LocalList = RemoteIMap[RemoteI];934  bool AccExists = false;935  unsigned AccIndex = AccessList.size();936  for (auto Index : LocalList) {937    auto &A = AccessList[Index];938    if (A.getLocalInst() == &I) {939      AccExists = true;940      AccIndex = Index;941      break;942    }943  }944 945  auto AddToBins = [&](const AAPointerInfo::RangeList &ToAdd) {946    LLVM_DEBUG(if (ToAdd.size()) dbgs()947                   << "[AAPointerInfo] Inserting access in new offset bins\n";);948 949    for (auto Key : ToAdd) {950      LLVM_DEBUG(dbgs() << "    key " << Key << "\n");951      OffsetBins[Key].insert(AccIndex);952    }953  };954 955  if (!AccExists) {956    AccessList.emplace_back(&I, RemoteI, Ranges, Content, Kind, Ty);957    assert((AccessList.size() == AccIndex + 1) &&958           "New Access should have been at AccIndex");959    LocalList.push_back(AccIndex);960    AddToBins(AccessList[AccIndex].getRanges());961    return ChangeStatus::CHANGED;962  }963 964  // Combine the new Access with the existing Access, and then update the965  // mapping in the offset bins.966  AAPointerInfo::Access Acc(&I, RemoteI, Ranges, Content, Kind, Ty);967  auto &Current = AccessList[AccIndex];968  auto Before = Current;969  Current &= Acc;970  if (Current == Before)971    return ChangeStatus::UNCHANGED;972 973  auto &ExistingRanges = Before.getRanges();974  auto &NewRanges = Current.getRanges();975 976  // Ranges that are in the old access but not the new access need to be removed977  // from the offset bins.978  AAPointerInfo::RangeList ToRemove;979  AAPointerInfo::RangeList::set_difference(ExistingRanges, NewRanges, ToRemove);980  LLVM_DEBUG(if (ToRemove.size()) dbgs()981                 << "[AAPointerInfo] Removing access from old offset bins\n";);982 983  for (auto Key : ToRemove) {984    LLVM_DEBUG(dbgs() << "    key " << Key << "\n");985    assert(OffsetBins.count(Key) && "Existing Access must be in some bin.");986    auto &Bin = OffsetBins[Key];987    assert(Bin.count(AccIndex) &&988           "Expected bin to actually contain the Access.");989    Bin.erase(AccIndex);990  }991 992  // Ranges that are in the new access but not the old access need to be added993  // to the offset bins.994  AAPointerInfo::RangeList ToAdd;995  AAPointerInfo::RangeList::set_difference(NewRanges, ExistingRanges, ToAdd);996  AddToBins(ToAdd);997  return ChangeStatus::CHANGED;998}999 1000namespace {1001 1002#ifndef NDEBUG1003static raw_ostream &operator<<(raw_ostream &OS,1004                               const AAPointerInfo::OffsetInfo &OI) {1005  OS << llvm::interleaved_array(OI);1006  return OS;1007}1008#endif // NDEBUG1009 1010struct AAPointerInfoImpl1011    : public StateWrapper<AA::PointerInfo::State, AAPointerInfo> {1012  using BaseTy = StateWrapper<AA::PointerInfo::State, AAPointerInfo>;1013  AAPointerInfoImpl(const IRPosition &IRP, Attributor &A) : BaseTy(IRP) {}1014 1015  /// See AbstractAttribute::getAsStr().1016  const std::string getAsStr(Attributor *A) const override {1017    return std::string("PointerInfo ") +1018           (isValidState() ? (std::string("#") +1019                              std::to_string(OffsetBins.size()) + " bins")1020                           : "<invalid>") +1021           (reachesReturn()1022                ? (" (returned:" +1023                   join(map_range(ReturnedOffsets,1024                                  [](int64_t O) { return std::to_string(O); }),1025                        ", ") +1026                   ")")1027                : "");1028  }1029 1030  /// See AbstractAttribute::manifest(...).1031  ChangeStatus manifest(Attributor &A) override {1032    return AAPointerInfo::manifest(A);1033  }1034 1035  const_bin_iterator begin() const override { return State::begin(); }1036  const_bin_iterator end() const override { return State::end(); }1037  int64_t numOffsetBins() const override { return State::numOffsetBins(); }1038  bool reachesReturn() const override {1039    return !ReturnedOffsets.isUnassigned();1040  }1041  void addReturnedOffsetsTo(OffsetInfo &OI) const override {1042    if (ReturnedOffsets.isUnknown()) {1043      OI.setUnknown();1044      return;1045    }1046 1047    OffsetInfo MergedOI;1048    for (auto Offset : ReturnedOffsets) {1049      OffsetInfo TmpOI = OI;1050      TmpOI.addToAll(Offset);1051      MergedOI.merge(TmpOI);1052    }1053    OI = std::move(MergedOI);1054  }1055 1056  ChangeStatus setReachesReturn(const OffsetInfo &ReachedReturnedOffsets) {1057    if (ReturnedOffsets.isUnknown())1058      return ChangeStatus::UNCHANGED;1059    if (ReachedReturnedOffsets.isUnknown()) {1060      ReturnedOffsets.setUnknown();1061      return ChangeStatus::CHANGED;1062    }1063    if (ReturnedOffsets.merge(ReachedReturnedOffsets))1064      return ChangeStatus::CHANGED;1065    return ChangeStatus::UNCHANGED;1066  }1067 1068  bool forallInterferingAccesses(1069      AA::RangeTy Range,1070      function_ref<bool(const AAPointerInfo::Access &, bool)> CB)1071      const override {1072    return State::forallInterferingAccesses(Range, CB);1073  }1074 1075  bool forallInterferingAccesses(1076      Attributor &A, const AbstractAttribute &QueryingAA, Instruction &I,1077      bool FindInterferingWrites, bool FindInterferingReads,1078      function_ref<bool(const Access &, bool)> UserCB, bool &HasBeenWrittenTo,1079      AA::RangeTy &Range,1080      function_ref<bool(const Access &)> SkipCB) const override {1081    HasBeenWrittenTo = false;1082 1083    SmallPtrSet<const Access *, 8> DominatingWrites;1084    SmallVector<std::pair<const Access *, bool>, 8> InterferingAccesses;1085 1086    Function &Scope = *I.getFunction();1087    bool IsKnownNoSync;1088    bool IsAssumedNoSync = AA::hasAssumedIRAttr<Attribute::NoSync>(1089        A, &QueryingAA, IRPosition::function(Scope), DepClassTy::OPTIONAL,1090        IsKnownNoSync);1091    const auto *ExecDomainAA = A.lookupAAFor<AAExecutionDomain>(1092        IRPosition::function(Scope), &QueryingAA, DepClassTy::NONE);1093    bool AllInSameNoSyncFn = IsAssumedNoSync;1094    bool InstIsExecutedByInitialThreadOnly =1095        ExecDomainAA && ExecDomainAA->isExecutedByInitialThreadOnly(I);1096 1097    // If the function is not ending in aligned barriers, we need the stores to1098    // be in aligned barriers. The load being in one is not sufficient since the1099    // store might be executed by a thread that disappears after, causing the1100    // aligned barrier guarding the load to unblock and the load to read a value1101    // that has no CFG path to the load.1102    bool InstIsExecutedInAlignedRegion =1103        FindInterferingReads && ExecDomainAA &&1104        ExecDomainAA->isExecutedInAlignedRegion(A, I);1105 1106    if (InstIsExecutedInAlignedRegion || InstIsExecutedByInitialThreadOnly)1107      A.recordDependence(*ExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);1108 1109    InformationCache &InfoCache = A.getInfoCache();1110    bool IsThreadLocalObj =1111        AA::isAssumedThreadLocalObject(A, getAssociatedValue(), *this);1112 1113    // Helper to determine if we need to consider threading, which we cannot1114    // right now. However, if the function is (assumed) nosync or the thread1115    // executing all instructions is the main thread only we can ignore1116    // threading. Also, thread-local objects do not require threading reasoning.1117    // Finally, we can ignore threading if either access is executed in an1118    // aligned region.1119    auto CanIgnoreThreadingForInst = [&](const Instruction &I) -> bool {1120      if (IsThreadLocalObj || AllInSameNoSyncFn)1121        return true;1122      const auto *FnExecDomainAA =1123          I.getFunction() == &Scope1124              ? ExecDomainAA1125              : A.lookupAAFor<AAExecutionDomain>(1126                    IRPosition::function(*I.getFunction()), &QueryingAA,1127                    DepClassTy::NONE);1128      if (!FnExecDomainAA)1129        return false;1130      if (InstIsExecutedInAlignedRegion ||1131          (FindInterferingWrites &&1132           FnExecDomainAA->isExecutedInAlignedRegion(A, I))) {1133        A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);1134        return true;1135      }1136      if (InstIsExecutedByInitialThreadOnly &&1137          FnExecDomainAA->isExecutedByInitialThreadOnly(I)) {1138        A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);1139        return true;1140      }1141      return false;1142    };1143 1144    // Helper to determine if the access is executed by the same thread as the1145    // given instruction, for now it is sufficient to avoid any potential1146    // threading effects as we cannot deal with them anyway.1147    auto CanIgnoreThreading = [&](const Access &Acc) -> bool {1148      return CanIgnoreThreadingForInst(*Acc.getRemoteInst()) ||1149             (Acc.getRemoteInst() != Acc.getLocalInst() &&1150              CanIgnoreThreadingForInst(*Acc.getLocalInst()));1151    };1152 1153    // TODO: Use inter-procedural reachability and dominance.1154    bool IsKnownNoRecurse;1155    AA::hasAssumedIRAttr<Attribute::NoRecurse>(1156        A, this, IRPosition::function(Scope), DepClassTy::OPTIONAL,1157        IsKnownNoRecurse);1158 1159    // TODO: Use reaching kernels from AAKernelInfo (or move it to1160    // AAExecutionDomain) such that we allow scopes other than kernels as long1161    // as the reaching kernels are disjoint.1162    bool InstInKernel = A.getInfoCache().isKernel(Scope);1163    bool ObjHasKernelLifetime = false;1164    const bool UseDominanceReasoning =1165        FindInterferingWrites && IsKnownNoRecurse;1166    const DominatorTree *DT =1167        InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(Scope);1168 1169    // Helper to check if a value has "kernel lifetime", that is it will not1170    // outlive a GPU kernel. This is true for shared, constant, and local1171    // globals on AMD and NVIDIA GPUs.1172    auto HasKernelLifetime = [&](Value *V, Module &M) {1173      if (!AA::isGPU(M))1174        return false;1175      switch (AA::GPUAddressSpace(V->getType()->getPointerAddressSpace())) {1176      case AA::GPUAddressSpace::Shared:1177      case AA::GPUAddressSpace::Constant:1178      case AA::GPUAddressSpace::Local:1179        return true;1180      default:1181        return false;1182      };1183    };1184 1185    // The IsLiveInCalleeCB will be used by the AA::isPotentiallyReachable query1186    // to determine if we should look at reachability from the callee. For1187    // certain pointers we know the lifetime and we do not have to step into the1188    // callee to determine reachability as the pointer would be dead in the1189    // callee. See the conditional initialization below.1190    std::function<bool(const Function &)> IsLiveInCalleeCB;1191 1192    if (auto *AI = dyn_cast<AllocaInst>(&getAssociatedValue())) {1193      // If the alloca containing function is not recursive the alloca1194      // must be dead in the callee.1195      const Function *AIFn = AI->getFunction();1196      ObjHasKernelLifetime = A.getInfoCache().isKernel(*AIFn);1197      bool IsKnownNoRecurse;1198      if (AA::hasAssumedIRAttr<Attribute::NoRecurse>(1199              A, this, IRPosition::function(*AIFn), DepClassTy::OPTIONAL,1200              IsKnownNoRecurse)) {1201        IsLiveInCalleeCB = [AIFn](const Function &Fn) { return AIFn != &Fn; };1202      }1203    } else if (auto *GV = dyn_cast<GlobalValue>(&getAssociatedValue())) {1204      // If the global has kernel lifetime we can stop if we reach a kernel1205      // as it is "dead" in the (unknown) callees.1206      ObjHasKernelLifetime = HasKernelLifetime(GV, *GV->getParent());1207      if (ObjHasKernelLifetime)1208        IsLiveInCalleeCB = [&A](const Function &Fn) {1209          return !A.getInfoCache().isKernel(Fn);1210        };1211    }1212 1213    // Set of accesses/instructions that will overwrite the result and are1214    // therefore blockers in the reachability traversal.1215    AA::InstExclusionSetTy ExclusionSet;1216 1217    auto AccessCB = [&](const Access &Acc, bool Exact) {1218      Function *AccScope = Acc.getRemoteInst()->getFunction();1219      bool AccInSameScope = AccScope == &Scope;1220 1221      // If the object has kernel lifetime we can ignore accesses only reachable1222      // by other kernels. For now we only skip accesses *in* other kernels.1223      if (InstInKernel && ObjHasKernelLifetime && !AccInSameScope &&1224          A.getInfoCache().isKernel(*AccScope))1225        return true;1226 1227      if (Exact && Acc.isMustAccess() && Acc.getRemoteInst() != &I) {1228        if (Acc.isWrite() || (isa<LoadInst>(I) && Acc.isWriteOrAssumption()))1229          ExclusionSet.insert(Acc.getRemoteInst());1230      }1231 1232      if ((!FindInterferingWrites || !Acc.isWriteOrAssumption()) &&1233          (!FindInterferingReads || !Acc.isRead()))1234        return true;1235 1236      bool Dominates = FindInterferingWrites && DT && Exact &&1237                       Acc.isMustAccess() && AccInSameScope &&1238                       DT->dominates(Acc.getRemoteInst(), &I);1239      if (Dominates)1240        DominatingWrites.insert(&Acc);1241 1242      // Track if all interesting accesses are in the same `nosync` function as1243      // the given instruction.1244      AllInSameNoSyncFn &= Acc.getRemoteInst()->getFunction() == &Scope;1245 1246      InterferingAccesses.push_back({&Acc, Exact});1247      return true;1248    };1249    if (!State::forallInterferingAccesses(I, AccessCB, Range))1250      return false;1251 1252    HasBeenWrittenTo = !DominatingWrites.empty();1253 1254    // Dominating writes form a chain, find the least/lowest member.1255    Instruction *LeastDominatingWriteInst = nullptr;1256    for (const Access *Acc : DominatingWrites) {1257      if (!LeastDominatingWriteInst) {1258        LeastDominatingWriteInst = Acc->getRemoteInst();1259      } else if (DT->dominates(LeastDominatingWriteInst,1260                               Acc->getRemoteInst())) {1261        LeastDominatingWriteInst = Acc->getRemoteInst();1262      }1263    }1264 1265    // Helper to determine if we can skip a specific write access.1266    auto CanSkipAccess = [&](const Access &Acc, bool Exact) {1267      if (SkipCB && SkipCB(Acc))1268        return true;1269      if (!CanIgnoreThreading(Acc))1270        return false;1271 1272      // Check read (RAW) dependences and write (WAR) dependences as necessary.1273      // If we successfully excluded all effects we are interested in, the1274      // access can be skipped.1275      bool ReadChecked = !FindInterferingReads;1276      bool WriteChecked = !FindInterferingWrites;1277 1278      // If the instruction cannot reach the access, the former does not1279      // interfere with what the access reads.1280      if (!ReadChecked) {1281        if (!AA::isPotentiallyReachable(A, I, *Acc.getRemoteInst(), QueryingAA,1282                                        &ExclusionSet, IsLiveInCalleeCB))1283          ReadChecked = true;1284      }1285      // If the instruction cannot be reach from the access, the latter does not1286      // interfere with what the instruction reads.1287      if (!WriteChecked) {1288        if (!AA::isPotentiallyReachable(A, *Acc.getRemoteInst(), I, QueryingAA,1289                                        &ExclusionSet, IsLiveInCalleeCB))1290          WriteChecked = true;1291      }1292 1293      // If we still might be affected by the write of the access but there are1294      // dominating writes in the function of the instruction1295      // (HasBeenWrittenTo), we can try to reason that the access is overwritten1296      // by them. This would have happend above if they are all in the same1297      // function, so we only check the inter-procedural case. Effectively, we1298      // want to show that there is no call after the dominting write that might1299      // reach the access, and when it returns reach the instruction with the1300      // updated value. To this end, we iterate all call sites, check if they1301      // might reach the instruction without going through another access1302      // (ExclusionSet) and at the same time might reach the access. However,1303      // that is all part of AAInterFnReachability.1304      if (!WriteChecked && HasBeenWrittenTo &&1305          Acc.getRemoteInst()->getFunction() != &Scope) {1306 1307        const auto *FnReachabilityAA = A.getAAFor<AAInterFnReachability>(1308            QueryingAA, IRPosition::function(Scope), DepClassTy::OPTIONAL);1309        if (FnReachabilityAA) {1310          // Without going backwards in the call tree, can we reach the access1311          // from the least dominating write. Do not allow to pass the1312          // instruction itself either.1313          bool Inserted = ExclusionSet.insert(&I).second;1314 1315          if (!FnReachabilityAA->instructionCanReach(1316                  A, *LeastDominatingWriteInst,1317                  *Acc.getRemoteInst()->getFunction(), &ExclusionSet))1318            WriteChecked = true;1319 1320          if (Inserted)1321            ExclusionSet.erase(&I);1322        }1323      }1324 1325      if (ReadChecked && WriteChecked)1326        return true;1327 1328      if (!DT || !UseDominanceReasoning)1329        return false;1330      if (!DominatingWrites.count(&Acc))1331        return false;1332      return LeastDominatingWriteInst != Acc.getRemoteInst();1333    };1334 1335    // Run the user callback on all accesses we cannot skip and return if1336    // that succeeded for all or not.1337    for (auto &It : InterferingAccesses) {1338      if ((!AllInSameNoSyncFn && !IsThreadLocalObj && !ExecDomainAA) ||1339          !CanSkipAccess(*It.first, It.second)) {1340        if (!UserCB(*It.first, It.second))1341          return false;1342      }1343    }1344    return true;1345  }1346 1347  ChangeStatus translateAndAddStateFromCallee(Attributor &A,1348                                              const AAPointerInfo &OtherAA,1349                                              CallBase &CB) {1350    using namespace AA::PointerInfo;1351    if (!OtherAA.getState().isValidState() || !isValidState())1352      return indicatePessimisticFixpoint();1353 1354    ChangeStatus Changed = ChangeStatus::UNCHANGED;1355    const auto &OtherAAImpl = static_cast<const AAPointerInfoImpl &>(OtherAA);1356    bool IsByval = OtherAAImpl.getAssociatedArgument()->hasByValAttr();1357    Changed |= setReachesReturn(OtherAAImpl.ReturnedOffsets);1358 1359    // Combine the accesses bin by bin.1360    const auto &State = OtherAAImpl.getState();1361    for (const auto &It : State) {1362      for (auto Index : It.getSecond()) {1363        const auto &RAcc = State.getAccess(Index);1364        if (IsByval && !RAcc.isRead())1365          continue;1366        bool UsedAssumedInformation = false;1367        AccessKind AK = RAcc.getKind();1368        auto Content = A.translateArgumentToCallSiteContent(1369            RAcc.getContent(), CB, *this, UsedAssumedInformation);1370        AK = AccessKind(AK & (IsByval ? AccessKind::AK_R : AccessKind::AK_RW));1371        AK = AccessKind(AK | (RAcc.isMayAccess() ? AK_MAY : AK_MUST));1372 1373        Changed |= addAccess(A, RAcc.getRanges(), CB, Content, AK,1374                             RAcc.getType(), RAcc.getRemoteInst());1375      }1376    }1377    return Changed;1378  }1379 1380  ChangeStatus translateAndAddState(Attributor &A, const AAPointerInfo &OtherAA,1381                                    const OffsetInfo &Offsets, CallBase &CB,1382                                    bool IsMustAcc) {1383    using namespace AA::PointerInfo;1384    if (!OtherAA.getState().isValidState() || !isValidState())1385      return indicatePessimisticFixpoint();1386 1387    const auto &OtherAAImpl = static_cast<const AAPointerInfoImpl &>(OtherAA);1388 1389    // Combine the accesses bin by bin.1390    ChangeStatus Changed = ChangeStatus::UNCHANGED;1391    const auto &State = OtherAAImpl.getState();1392    for (const auto &It : State) {1393      for (auto Index : It.getSecond()) {1394        const auto &RAcc = State.getAccess(Index);1395        if (!IsMustAcc && RAcc.isAssumption())1396          continue;1397        for (auto Offset : Offsets) {1398          auto NewRanges = Offset == AA::RangeTy::Unknown1399                               ? AA::RangeTy::getUnknown()1400                               : RAcc.getRanges();1401          if (!NewRanges.isUnknown()) {1402            NewRanges.addToAllOffsets(Offset);1403          }1404          AccessKind AK = RAcc.getKind();1405          if (!IsMustAcc)1406            AK = AccessKind((AK & ~AK_MUST) | AK_MAY);1407          Changed |= addAccess(A, NewRanges, CB, RAcc.getContent(), AK,1408                               RAcc.getType(), RAcc.getRemoteInst());1409        }1410      }1411    }1412    return Changed;1413  }1414 1415  /// Statistic tracking for all AAPointerInfo implementations.1416  /// See AbstractAttribute::trackStatistics().1417  void trackPointerInfoStatistics(const IRPosition &IRP) const {}1418 1419  /// Dump the state into \p O.1420  void dumpState(raw_ostream &O) {1421    for (auto &It : OffsetBins) {1422      O << "[" << It.first.Offset << "-" << It.first.Offset + It.first.Size1423        << "] : " << It.getSecond().size() << "\n";1424      for (auto AccIndex : It.getSecond()) {1425        auto &Acc = AccessList[AccIndex];1426        O << "     - " << Acc.getKind() << " - " << *Acc.getLocalInst() << "\n";1427        if (Acc.getLocalInst() != Acc.getRemoteInst())1428          O << "     -->                         " << *Acc.getRemoteInst()1429            << "\n";1430        if (!Acc.isWrittenValueYetUndetermined()) {1431          if (isa_and_nonnull<Function>(Acc.getWrittenValue()))1432            O << "       - c: func " << Acc.getWrittenValue()->getName()1433              << "\n";1434          else if (Acc.getWrittenValue())1435            O << "       - c: " << *Acc.getWrittenValue() << "\n";1436          else1437            O << "       - c: <unknown>\n";1438        }1439      }1440    }1441  }1442};1443 1444struct AAPointerInfoFloating : public AAPointerInfoImpl {1445  using AccessKind = AAPointerInfo::AccessKind;1446  AAPointerInfoFloating(const IRPosition &IRP, Attributor &A)1447      : AAPointerInfoImpl(IRP, A) {}1448 1449  /// Deal with an access and signal if it was handled successfully.1450  bool handleAccess(Attributor &A, Instruction &I,1451                    std::optional<Value *> Content, AccessKind Kind,1452                    OffsetInfo::VecTy &Offsets, ChangeStatus &Changed,1453                    Type &Ty) {1454    using namespace AA::PointerInfo;1455    auto Size = AA::RangeTy::Unknown;1456    const DataLayout &DL = A.getDataLayout();1457    TypeSize AccessSize = DL.getTypeStoreSize(&Ty);1458    if (!AccessSize.isScalable())1459      Size = AccessSize.getFixedValue();1460 1461    // Make a strictly ascending list of offsets as required by addAccess()1462    SmallVector<int64_t> OffsetsSorted(Offsets.begin(), Offsets.end());1463    llvm::sort(OffsetsSorted);1464 1465    VectorType *VT = dyn_cast<VectorType>(&Ty);1466    if (!VT || VT->getElementCount().isScalable() ||1467        !Content.value_or(nullptr) || !isa<Constant>(*Content) ||1468        (*Content)->getType() != VT ||1469        DL.getTypeStoreSize(VT->getElementType()).isScalable()) {1470      Changed =1471          Changed | addAccess(A, {OffsetsSorted, Size}, I, Content, Kind, &Ty);1472    } else {1473      // Handle vector stores with constant content element-wise.1474      // TODO: We could look for the elements or create instructions1475      //       representing them.1476      // TODO: We need to push the Content into the range abstraction1477      //       (AA::RangeTy) to allow different content values for different1478      //       ranges. ranges. Hence, support vectors storing different values.1479      Type *ElementType = VT->getElementType();1480      int64_t ElementSize = DL.getTypeStoreSize(ElementType).getFixedValue();1481      auto *ConstContent = cast<Constant>(*Content);1482      Type *Int32Ty = Type::getInt32Ty(ElementType->getContext());1483      SmallVector<int64_t> ElementOffsets(Offsets.begin(), Offsets.end());1484 1485      for (int i = 0, e = VT->getElementCount().getFixedValue(); i != e; ++i) {1486        Value *ElementContent = ConstantExpr::getExtractElement(1487            ConstContent, ConstantInt::get(Int32Ty, i));1488 1489        // Add the element access.1490        Changed = Changed | addAccess(A, {ElementOffsets, ElementSize}, I,1491                                      ElementContent, Kind, ElementType);1492 1493        // Advance the offsets for the next element.1494        for (auto &ElementOffset : ElementOffsets)1495          ElementOffset += ElementSize;1496      }1497    }1498    return true;1499  };1500 1501  /// See AbstractAttribute::updateImpl(...).1502  ChangeStatus updateImpl(Attributor &A) override;1503 1504  /// If the indices to \p GEP can be traced to constants, incorporate all1505  /// of these into \p UsrOI.1506  ///1507  /// \return true iff \p UsrOI is updated.1508  bool collectConstantsForGEP(Attributor &A, const DataLayout &DL,1509                              OffsetInfo &UsrOI, const OffsetInfo &PtrOI,1510                              const GEPOperator *GEP);1511 1512  /// See AbstractAttribute::trackStatistics()1513  void trackStatistics() const override {1514    AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());1515  }1516};1517 1518bool AAPointerInfoFloating::collectConstantsForGEP(Attributor &A,1519                                                   const DataLayout &DL,1520                                                   OffsetInfo &UsrOI,1521                                                   const OffsetInfo &PtrOI,1522                                                   const GEPOperator *GEP) {1523  unsigned BitWidth = DL.getIndexTypeSizeInBits(GEP->getType());1524  SmallMapVector<Value *, APInt, 4> VariableOffsets;1525  APInt ConstantOffset(BitWidth, 0);1526 1527  assert(!UsrOI.isUnknown() && !PtrOI.isUnknown() &&1528         "Don't look for constant values if the offset has already been "1529         "determined to be unknown.");1530 1531  if (!GEP->collectOffset(DL, BitWidth, VariableOffsets, ConstantOffset)) {1532    UsrOI.setUnknown();1533    return true;1534  }1535 1536  LLVM_DEBUG(dbgs() << "[AAPointerInfo] GEP offset is "1537                    << (VariableOffsets.empty() ? "" : "not") << " constant "1538                    << *GEP << "\n");1539 1540  auto Union = PtrOI;1541  Union.addToAll(ConstantOffset.getSExtValue());1542 1543  // Each VI in VariableOffsets has a set of potential constant values. Every1544  // combination of elements, picked one each from these sets, is separately1545  // added to the original set of offsets, thus resulting in more offsets.1546  for (const auto &VI : VariableOffsets) {1547    auto *PotentialConstantsAA = A.getAAFor<AAPotentialConstantValues>(1548        *this, IRPosition::value(*VI.first), DepClassTy::OPTIONAL);1549    if (!PotentialConstantsAA || !PotentialConstantsAA->isValidState()) {1550      UsrOI.setUnknown();1551      return true;1552    }1553 1554    // UndefValue is treated as a zero, which leaves Union as is.1555    if (PotentialConstantsAA->undefIsContained())1556      continue;1557 1558    // We need at least one constant in every set to compute an actual offset.1559    // Otherwise, we end up pessimizing AAPointerInfo by respecting offsets that1560    // don't actually exist. In other words, the absence of constant values1561    // implies that the operation can be assumed dead for now.1562    auto &AssumedSet = PotentialConstantsAA->getAssumedSet();1563    if (AssumedSet.empty())1564      return false;1565 1566    OffsetInfo Product;1567    for (const auto &ConstOffset : AssumedSet) {1568      auto CopyPerOffset = Union;1569      CopyPerOffset.addToAll(ConstOffset.getSExtValue() *1570                             VI.second.getZExtValue());1571      Product.merge(CopyPerOffset);1572    }1573    Union = Product;1574  }1575 1576  UsrOI = std::move(Union);1577  return true;1578}1579 1580ChangeStatus AAPointerInfoFloating::updateImpl(Attributor &A) {1581  using namespace AA::PointerInfo;1582  ChangeStatus Changed = ChangeStatus::UNCHANGED;1583  const DataLayout &DL = A.getDataLayout();1584  Value &AssociatedValue = getAssociatedValue();1585 1586  DenseMap<Value *, OffsetInfo> OffsetInfoMap;1587  OffsetInfoMap[&AssociatedValue].insert(0);1588 1589  auto HandlePassthroughUser = [&](Value *Usr, Value *CurPtr, bool &Follow) {1590    // One does not simply walk into a map and assign a reference to a possibly1591    // new location. That can cause an invalidation before the assignment1592    // happens, like so:1593    //1594    //   OffsetInfoMap[Usr] = OffsetInfoMap[CurPtr]; /* bad idea! */1595    //1596    // The RHS is a reference that may be invalidated by an insertion caused by1597    // the LHS. So we ensure that the side-effect of the LHS happens first.1598 1599    assert(OffsetInfoMap.contains(CurPtr) &&1600           "CurPtr does not exist in the map!");1601 1602    auto &UsrOI = OffsetInfoMap[Usr];1603    auto &PtrOI = OffsetInfoMap[CurPtr];1604    assert(!PtrOI.isUnassigned() &&1605           "Cannot pass through if the input Ptr was not visited!");1606    UsrOI.merge(PtrOI);1607    Follow = true;1608    return true;1609  };1610 1611  auto UsePred = [&](const Use &U, bool &Follow) -> bool {1612    Value *CurPtr = U.get();1613    User *Usr = U.getUser();1614    LLVM_DEBUG(dbgs() << "[AAPointerInfo] Analyze " << *CurPtr << " in " << *Usr1615                      << "\n");1616    assert(OffsetInfoMap.count(CurPtr) &&1617           "The current pointer offset should have been seeded!");1618    assert(!OffsetInfoMap[CurPtr].isUnassigned() &&1619           "Current pointer should be assigned");1620 1621    if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Usr)) {1622      if (CE->isCast())1623        return HandlePassthroughUser(Usr, CurPtr, Follow);1624      if (!isa<GEPOperator>(CE)) {1625        LLVM_DEBUG(dbgs() << "[AAPointerInfo] Unhandled constant user " << *CE1626                          << "\n");1627        return false;1628      }1629    }1630    if (auto *GEP = dyn_cast<GEPOperator>(Usr)) {1631      // Note the order here, the Usr access might change the map, CurPtr is1632      // already in it though.1633      auto &UsrOI = OffsetInfoMap[Usr];1634      auto &PtrOI = OffsetInfoMap[CurPtr];1635 1636      if (UsrOI.isUnknown())1637        return true;1638 1639      if (PtrOI.isUnknown()) {1640        Follow = true;1641        UsrOI.setUnknown();1642        return true;1643      }1644 1645      Follow = collectConstantsForGEP(A, DL, UsrOI, PtrOI, GEP);1646      return true;1647    }1648    if (isa<PtrToIntInst>(Usr))1649      return false;1650    if (isa<CastInst>(Usr) || isa<SelectInst>(Usr))1651      return HandlePassthroughUser(Usr, CurPtr, Follow);1652    // Returns are allowed if they are in the associated functions. Users can1653    // then check the call site return. Returns from other functions can't be1654    // tracked and are cause for invalidation.1655    if (auto *RI = dyn_cast<ReturnInst>(Usr)) {1656      if (RI->getFunction() == getAssociatedFunction()) {1657        auto &PtrOI = OffsetInfoMap[CurPtr];1658        Changed |= setReachesReturn(PtrOI);1659        return true;1660      }1661      return false;1662    }1663 1664    // For PHIs we need to take care of the recurrence explicitly as the value1665    // might change while we iterate through a loop. For now, we give up if1666    // the PHI is not invariant.1667    if (auto *PHI = dyn_cast<PHINode>(Usr)) {1668      // Note the order here, the Usr access might change the map, CurPtr is1669      // already in it though.1670      auto [PhiIt, IsFirstPHIUser] = OffsetInfoMap.try_emplace(PHI);1671      auto &UsrOI = PhiIt->second;1672      auto &PtrOI = OffsetInfoMap[CurPtr];1673 1674      // Check if the PHI operand has already an unknown offset as we can't1675      // improve on that anymore.1676      if (PtrOI.isUnknown()) {1677        LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI operand offset unknown "1678                          << *CurPtr << " in " << *PHI << "\n");1679        Follow = !UsrOI.isUnknown();1680        UsrOI.setUnknown();1681        return true;1682      }1683 1684      // Check if the PHI is invariant (so far).1685      if (UsrOI == PtrOI) {1686        assert(!PtrOI.isUnassigned() &&1687               "Cannot assign if the current Ptr was not visited!");1688        LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI is invariant (so far)");1689        return true;1690      }1691 1692      // Check if the PHI operand can be traced back to AssociatedValue.1693      APInt Offset(1694          DL.getIndexSizeInBits(CurPtr->getType()->getPointerAddressSpace()),1695          0);1696      Value *CurPtrBase = CurPtr->stripAndAccumulateConstantOffsets(1697          DL, Offset, /* AllowNonInbounds */ true);1698      auto It = OffsetInfoMap.find(CurPtrBase);1699      if (It == OffsetInfoMap.end()) {1700        LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI operand is too complex "1701                          << *CurPtr << " in " << *PHI1702                          << " (base: " << *CurPtrBase << ")\n");1703        UsrOI.setUnknown();1704        Follow = true;1705        return true;1706      }1707 1708      // Check if the PHI operand is not dependent on the PHI itself. Every1709      // recurrence is a cyclic net of PHIs in the data flow, and has an1710      // equivalent Cycle in the control flow. One of those PHIs must be in the1711      // header of that control flow Cycle. This is independent of the choice of1712      // Cycles reported by CycleInfo. It is sufficient to check the PHIs in1713      // every Cycle header; if such a node is marked unknown, this will1714      // eventually propagate through the whole net of PHIs in the recurrence.1715      const auto *CI =1716          A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(1717              *PHI->getFunction());1718      if (mayBeInCycle(CI, cast<Instruction>(Usr), /* HeaderOnly */ true)) {1719        auto BaseOI = It->getSecond();1720        BaseOI.addToAll(Offset.getZExtValue());1721        if (IsFirstPHIUser || BaseOI == UsrOI) {1722          LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI is invariant " << *CurPtr1723                            << " in " << *Usr << "\n");1724          return HandlePassthroughUser(Usr, CurPtr, Follow);1725        }1726 1727        LLVM_DEBUG(1728            dbgs() << "[AAPointerInfo] PHI operand pointer offset mismatch "1729                   << *CurPtr << " in " << *PHI << "\n");1730        UsrOI.setUnknown();1731        Follow = true;1732        return true;1733      }1734 1735      UsrOI.merge(PtrOI);1736      Follow = true;1737      return true;1738    }1739 1740    if (auto *LoadI = dyn_cast<LoadInst>(Usr)) {1741      // If the access is to a pointer that may or may not be the associated1742      // value, e.g. due to a PHI, we cannot assume it will be read.1743      AccessKind AK = AccessKind::AK_R;1744      if (getUnderlyingObject(CurPtr) == &AssociatedValue)1745        AK = AccessKind(AK | AccessKind::AK_MUST);1746      else1747        AK = AccessKind(AK | AccessKind::AK_MAY);1748      if (!handleAccess(A, *LoadI, /* Content */ nullptr, AK,1749                        OffsetInfoMap[CurPtr].Offsets, Changed,1750                        *LoadI->getType()))1751        return false;1752 1753      auto IsAssumption = [](Instruction &I) {1754        if (auto *II = dyn_cast<IntrinsicInst>(&I))1755          return II->isAssumeLikeIntrinsic();1756        return false;1757      };1758 1759      auto IsImpactedInRange = [&](Instruction *FromI, Instruction *ToI) {1760        // Check if the assumption and the load are executed together without1761        // memory modification.1762        do {1763          if (FromI->mayWriteToMemory() && !IsAssumption(*FromI))1764            return true;1765          FromI = FromI->getNextNode();1766        } while (FromI && FromI != ToI);1767        return false;1768      };1769 1770      BasicBlock *BB = LoadI->getParent();1771      auto IsValidAssume = [&](IntrinsicInst &IntrI) {1772        if (IntrI.getIntrinsicID() != Intrinsic::assume)1773          return false;1774        BasicBlock *IntrBB = IntrI.getParent();1775        if (IntrI.getParent() == BB) {1776          if (IsImpactedInRange(LoadI->getNextNode(), &IntrI))1777            return false;1778        } else {1779          auto PredIt = pred_begin(IntrBB);1780          if (PredIt == pred_end(IntrBB))1781            return false;1782          if ((*PredIt) != BB)1783            return false;1784          if (++PredIt != pred_end(IntrBB))1785            return false;1786          for (auto *SuccBB : successors(BB)) {1787            if (SuccBB == IntrBB)1788              continue;1789            if (isa<UnreachableInst>(SuccBB->getTerminator()))1790              continue;1791            return false;1792          }1793          if (IsImpactedInRange(LoadI->getNextNode(), BB->getTerminator()))1794            return false;1795          if (IsImpactedInRange(&IntrBB->front(), &IntrI))1796            return false;1797        }1798        return true;1799      };1800 1801      std::pair<Value *, IntrinsicInst *> Assumption;1802      for (const Use &LoadU : LoadI->uses()) {1803        if (auto *CmpI = dyn_cast<CmpInst>(LoadU.getUser())) {1804          if (!CmpI->isEquality() || !CmpI->isTrueWhenEqual())1805            continue;1806          for (const Use &CmpU : CmpI->uses()) {1807            if (auto *IntrI = dyn_cast<IntrinsicInst>(CmpU.getUser())) {1808              if (!IsValidAssume(*IntrI))1809                continue;1810              int Idx = CmpI->getOperandUse(0) == LoadU;1811              Assumption = {CmpI->getOperand(Idx), IntrI};1812              break;1813            }1814          }1815        }1816        if (Assumption.first)1817          break;1818      }1819 1820      // Check if we found an assumption associated with this load.1821      if (!Assumption.first || !Assumption.second)1822        return true;1823 1824      LLVM_DEBUG(dbgs() << "[AAPointerInfo] Assumption found "1825                        << *Assumption.second << ": " << *LoadI1826                        << " == " << *Assumption.first << "\n");1827      bool UsedAssumedInformation = false;1828      std::optional<Value *> Content = nullptr;1829      if (Assumption.first)1830        Content =1831            A.getAssumedSimplified(*Assumption.first, *this,1832                                   UsedAssumedInformation, AA::Interprocedural);1833      return handleAccess(1834          A, *Assumption.second, Content, AccessKind::AK_ASSUMPTION,1835          OffsetInfoMap[CurPtr].Offsets, Changed, *LoadI->getType());1836    }1837 1838    auto HandleStoreLike = [&](Instruction &I, Value *ValueOp, Type &ValueTy,1839                               ArrayRef<Value *> OtherOps, AccessKind AK) {1840      for (auto *OtherOp : OtherOps) {1841        if (OtherOp == CurPtr) {1842          LLVM_DEBUG(1843              dbgs()1844              << "[AAPointerInfo] Escaping use in store like instruction " << I1845              << "\n");1846          return false;1847        }1848      }1849 1850      // If the access is to a pointer that may or may not be the associated1851      // value, e.g. due to a PHI, we cannot assume it will be written.1852      if (getUnderlyingObject(CurPtr) == &AssociatedValue)1853        AK = AccessKind(AK | AccessKind::AK_MUST);1854      else1855        AK = AccessKind(AK | AccessKind::AK_MAY);1856      bool UsedAssumedInformation = false;1857      std::optional<Value *> Content = nullptr;1858      if (ValueOp)1859        Content = A.getAssumedSimplified(1860            *ValueOp, *this, UsedAssumedInformation, AA::Interprocedural);1861      return handleAccess(A, I, Content, AK, OffsetInfoMap[CurPtr].Offsets,1862                          Changed, ValueTy);1863    };1864 1865    if (auto *StoreI = dyn_cast<StoreInst>(Usr))1866      return HandleStoreLike(*StoreI, StoreI->getValueOperand(),1867                             *StoreI->getValueOperand()->getType(),1868                             {StoreI->getValueOperand()}, AccessKind::AK_W);1869    if (auto *RMWI = dyn_cast<AtomicRMWInst>(Usr))1870      return HandleStoreLike(*RMWI, nullptr, *RMWI->getValOperand()->getType(),1871                             {RMWI->getValOperand()}, AccessKind::AK_RW);1872    if (auto *CXI = dyn_cast<AtomicCmpXchgInst>(Usr))1873      return HandleStoreLike(1874          *CXI, nullptr, *CXI->getNewValOperand()->getType(),1875          {CXI->getCompareOperand(), CXI->getNewValOperand()},1876          AccessKind::AK_RW);1877 1878    if (auto *CB = dyn_cast<CallBase>(Usr)) {1879      if (CB->isLifetimeStartOrEnd())1880        return true;1881      const auto *TLI =1882          A.getInfoCache().getTargetLibraryInfoForFunction(*CB->getFunction());1883      if (getFreedOperand(CB, TLI) == U)1884        return true;1885      if (CB->isArgOperand(&U)) {1886        unsigned ArgNo = CB->getArgOperandNo(&U);1887        const auto *CSArgPI = A.getAAFor<AAPointerInfo>(1888            *this, IRPosition::callsite_argument(*CB, ArgNo),1889            DepClassTy::REQUIRED);1890        if (!CSArgPI)1891          return false;1892        bool IsArgMustAcc = (getUnderlyingObject(CurPtr) == &AssociatedValue);1893        Changed = translateAndAddState(A, *CSArgPI, OffsetInfoMap[CurPtr], *CB,1894                                       IsArgMustAcc) |1895                  Changed;1896        if (!CSArgPI->reachesReturn())1897          return isValidState();1898 1899        Function *Callee = CB->getCalledFunction();1900        if (!Callee || Callee->arg_size() <= ArgNo)1901          return false;1902        bool UsedAssumedInformation = false;1903        auto ReturnedValue = A.getAssumedSimplified(1904            IRPosition::returned(*Callee), *this, UsedAssumedInformation,1905            AA::ValueScope::Intraprocedural);1906        auto *ReturnedArg =1907            dyn_cast_or_null<Argument>(ReturnedValue.value_or(nullptr));1908        auto *Arg = Callee->getArg(ArgNo);1909        if (ReturnedArg && Arg != ReturnedArg)1910          return true;1911        bool IsRetMustAcc = IsArgMustAcc && (ReturnedArg == Arg);1912        const auto *CSRetPI = A.getAAFor<AAPointerInfo>(1913            *this, IRPosition::callsite_returned(*CB), DepClassTy::REQUIRED);1914        if (!CSRetPI)1915          return false;1916        OffsetInfo OI = OffsetInfoMap[CurPtr];1917        CSArgPI->addReturnedOffsetsTo(OI);1918        Changed =1919            translateAndAddState(A, *CSRetPI, OI, *CB, IsRetMustAcc) | Changed;1920        return isValidState();1921      }1922      LLVM_DEBUG(dbgs() << "[AAPointerInfo] Call user not handled " << *CB1923                        << "\n");1924      return false;1925    }1926 1927    LLVM_DEBUG(dbgs() << "[AAPointerInfo] User not handled " << *Usr << "\n");1928    return false;1929  };1930  auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {1931    assert(OffsetInfoMap.count(OldU) && "Old use should be known already!");1932    assert(!OffsetInfoMap[OldU].isUnassigned() && "Old use should be assinged");1933    if (OffsetInfoMap.count(NewU)) {1934      LLVM_DEBUG({1935        if (!(OffsetInfoMap[NewU] == OffsetInfoMap[OldU])) {1936          dbgs() << "[AAPointerInfo] Equivalent use callback failed: "1937                 << OffsetInfoMap[NewU] << " vs " << OffsetInfoMap[OldU]1938                 << "\n";1939        }1940      });1941      return OffsetInfoMap[NewU] == OffsetInfoMap[OldU];1942    }1943    bool Unused;1944    return HandlePassthroughUser(NewU.get(), OldU.get(), Unused);1945  };1946  if (!A.checkForAllUses(UsePred, *this, AssociatedValue,1947                         /* CheckBBLivenessOnly */ true, DepClassTy::OPTIONAL,1948                         /* IgnoreDroppableUses */ true, EquivalentUseCB)) {1949    LLVM_DEBUG(dbgs() << "[AAPointerInfo] Check for all uses failed, abort!\n");1950    return indicatePessimisticFixpoint();1951  }1952 1953  LLVM_DEBUG({1954    dbgs() << "Accesses by bin after update:\n";1955    dumpState(dbgs());1956  });1957 1958  return Changed;1959}1960 1961struct AAPointerInfoReturned final : AAPointerInfoImpl {1962  AAPointerInfoReturned(const IRPosition &IRP, Attributor &A)1963      : AAPointerInfoImpl(IRP, A) {}1964 1965  /// See AbstractAttribute::updateImpl(...).1966  ChangeStatus updateImpl(Attributor &A) override {1967    return indicatePessimisticFixpoint();1968  }1969 1970  /// See AbstractAttribute::trackStatistics()1971  void trackStatistics() const override {1972    AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());1973  }1974};1975 1976struct AAPointerInfoArgument final : AAPointerInfoFloating {1977  AAPointerInfoArgument(const IRPosition &IRP, Attributor &A)1978      : AAPointerInfoFloating(IRP, A) {}1979 1980  /// See AbstractAttribute::trackStatistics()1981  void trackStatistics() const override {1982    AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());1983  }1984};1985 1986struct AAPointerInfoCallSiteArgument final : AAPointerInfoFloating {1987  AAPointerInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)1988      : AAPointerInfoFloating(IRP, A) {}1989 1990  /// See AbstractAttribute::updateImpl(...).1991  ChangeStatus updateImpl(Attributor &A) override {1992    using namespace AA::PointerInfo;1993    // We handle memory intrinsics explicitly, at least the first (=1994    // destination) and second (=source) arguments as we know how they are1995    // accessed.1996    if (auto *MI = dyn_cast_or_null<MemIntrinsic>(getCtxI())) {1997      int64_t LengthVal = AA::RangeTy::Unknown;1998      if (auto Length = MI->getLengthInBytes())1999        LengthVal = Length->getSExtValue();2000      unsigned ArgNo = getIRPosition().getCallSiteArgNo();2001      ChangeStatus Changed = ChangeStatus::UNCHANGED;2002      if (ArgNo > 1) {2003        LLVM_DEBUG(dbgs() << "[AAPointerInfo] Unhandled memory intrinsic "2004                          << *MI << "\n");2005        return indicatePessimisticFixpoint();2006      } else {2007        auto Kind =2008            ArgNo == 0 ? AccessKind::AK_MUST_WRITE : AccessKind::AK_MUST_READ;2009        Changed =2010            Changed | addAccess(A, {0, LengthVal}, *MI, nullptr, Kind, nullptr);2011      }2012      LLVM_DEBUG({2013        dbgs() << "Accesses by bin after update:\n";2014        dumpState(dbgs());2015      });2016 2017      return Changed;2018    }2019 2020    // TODO: Once we have call site specific value information we can provide2021    //       call site specific liveness information and then it makes2022    //       sense to specialize attributes for call sites arguments instead of2023    //       redirecting requests to the callee argument.2024    Argument *Arg = getAssociatedArgument();2025    if (Arg) {2026      const IRPosition &ArgPos = IRPosition::argument(*Arg);2027      auto *ArgAA =2028          A.getAAFor<AAPointerInfo>(*this, ArgPos, DepClassTy::REQUIRED);2029      if (ArgAA && ArgAA->getState().isValidState())2030        return translateAndAddStateFromCallee(A, *ArgAA,2031                                              *cast<CallBase>(getCtxI()));2032      if (!Arg->getParent()->isDeclaration())2033        return indicatePessimisticFixpoint();2034    }2035 2036    bool IsKnownNoCapture;2037    if (!AA::hasAssumedIRAttr<Attribute::Captures>(2038            A, this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNoCapture))2039      return indicatePessimisticFixpoint();2040 2041    bool IsKnown = false;2042    if (AA::isAssumedReadNone(A, getIRPosition(), *this, IsKnown))2043      return ChangeStatus::UNCHANGED;2044    bool ReadOnly = AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown);2045    auto Kind =2046        ReadOnly ? AccessKind::AK_MAY_READ : AccessKind::AK_MAY_READ_WRITE;2047    return addAccess(A, AA::RangeTy::getUnknown(), *getCtxI(), nullptr, Kind,2048                     nullptr);2049  }2050 2051  /// See AbstractAttribute::trackStatistics()2052  void trackStatistics() const override {2053    AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());2054  }2055};2056 2057struct AAPointerInfoCallSiteReturned final : AAPointerInfoFloating {2058  AAPointerInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)2059      : AAPointerInfoFloating(IRP, A) {}2060 2061  /// See AbstractAttribute::trackStatistics()2062  void trackStatistics() const override {2063    AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());2064  }2065};2066} // namespace2067 2068/// -----------------------NoUnwind Function Attribute--------------------------2069 2070namespace {2071struct AANoUnwindImpl : AANoUnwind {2072  AANoUnwindImpl(const IRPosition &IRP, Attributor &A) : AANoUnwind(IRP, A) {}2073 2074  /// See AbstractAttribute::initialize(...).2075  void initialize(Attributor &A) override {2076    bool IsKnown;2077    assert(!AA::hasAssumedIRAttr<Attribute::NoUnwind>(2078        A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));2079    (void)IsKnown;2080  }2081 2082  const std::string getAsStr(Attributor *A) const override {2083    return getAssumed() ? "nounwind" : "may-unwind";2084  }2085 2086  /// See AbstractAttribute::updateImpl(...).2087  ChangeStatus updateImpl(Attributor &A) override {2088    auto Opcodes = {2089        (unsigned)Instruction::Invoke,      (unsigned)Instruction::CallBr,2090        (unsigned)Instruction::Call,        (unsigned)Instruction::CleanupRet,2091        (unsigned)Instruction::CatchSwitch, (unsigned)Instruction::Resume};2092 2093    auto CheckForNoUnwind = [&](Instruction &I) {2094      if (!I.mayThrow(/* IncludePhaseOneUnwind */ true))2095        return true;2096 2097      if (const auto *CB = dyn_cast<CallBase>(&I)) {2098        bool IsKnownNoUnwind;2099        return AA::hasAssumedIRAttr<Attribute::NoUnwind>(2100            A, this, IRPosition::callsite_function(*CB), DepClassTy::REQUIRED,2101            IsKnownNoUnwind);2102      }2103      return false;2104    };2105 2106    bool UsedAssumedInformation = false;2107    if (!A.checkForAllInstructions(CheckForNoUnwind, *this, Opcodes,2108                                   UsedAssumedInformation))2109      return indicatePessimisticFixpoint();2110 2111    return ChangeStatus::UNCHANGED;2112  }2113};2114 2115struct AANoUnwindFunction final : public AANoUnwindImpl {2116  AANoUnwindFunction(const IRPosition &IRP, Attributor &A)2117      : AANoUnwindImpl(IRP, A) {}2118 2119  /// See AbstractAttribute::trackStatistics()2120  void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nounwind) }2121};2122 2123/// NoUnwind attribute deduction for a call sites.2124struct AANoUnwindCallSite final2125    : AACalleeToCallSite<AANoUnwind, AANoUnwindImpl> {2126  AANoUnwindCallSite(const IRPosition &IRP, Attributor &A)2127      : AACalleeToCallSite<AANoUnwind, AANoUnwindImpl>(IRP, A) {}2128 2129  /// See AbstractAttribute::trackStatistics()2130  void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nounwind); }2131};2132} // namespace2133 2134/// ------------------------ NoSync Function Attribute -------------------------2135 2136bool AANoSync::isAlignedBarrier(const CallBase &CB, bool ExecutedAligned) {2137  switch (CB.getIntrinsicID()) {2138  case Intrinsic::nvvm_barrier_cta_sync_aligned_all:2139  case Intrinsic::nvvm_barrier_cta_sync_aligned_count:2140  case Intrinsic::nvvm_barrier0_and:2141  case Intrinsic::nvvm_barrier0_or:2142  case Intrinsic::nvvm_barrier0_popc:2143    return true;2144  case Intrinsic::amdgcn_s_barrier:2145    if (ExecutedAligned)2146      return true;2147    break;2148  default:2149    break;2150  }2151  return hasAssumption(CB, KnownAssumptionString("ompx_aligned_barrier"));2152}2153 2154bool AANoSync::isNonRelaxedAtomic(const Instruction *I) {2155  if (!I->isAtomic())2156    return false;2157 2158  if (auto *FI = dyn_cast<FenceInst>(I))2159    // All legal orderings for fence are stronger than monotonic.2160    return FI->getSyncScopeID() != SyncScope::SingleThread;2161  if (auto *AI = dyn_cast<AtomicCmpXchgInst>(I)) {2162    // Unordered is not a legal ordering for cmpxchg.2163    return (AI->getSuccessOrdering() != AtomicOrdering::Monotonic ||2164            AI->getFailureOrdering() != AtomicOrdering::Monotonic);2165  }2166 2167  AtomicOrdering Ordering;2168  switch (I->getOpcode()) {2169  case Instruction::AtomicRMW:2170    Ordering = cast<AtomicRMWInst>(I)->getOrdering();2171    break;2172  case Instruction::Store:2173    Ordering = cast<StoreInst>(I)->getOrdering();2174    break;2175  case Instruction::Load:2176    Ordering = cast<LoadInst>(I)->getOrdering();2177    break;2178  default:2179    llvm_unreachable(2180        "New atomic operations need to be known in the attributor.");2181  }2182 2183  return (Ordering != AtomicOrdering::Unordered &&2184          Ordering != AtomicOrdering::Monotonic);2185}2186 2187/// Return true if this intrinsic is nosync.  This is only used for intrinsics2188/// which would be nosync except that they have a volatile flag.  All other2189/// intrinsics are simply annotated with the nosync attribute in Intrinsics.td.2190bool AANoSync::isNoSyncIntrinsic(const Instruction *I) {2191  if (auto *MI = dyn_cast<MemIntrinsic>(I))2192    return !MI->isVolatile();2193  return false;2194}2195 2196namespace {2197struct AANoSyncImpl : AANoSync {2198  AANoSyncImpl(const IRPosition &IRP, Attributor &A) : AANoSync(IRP, A) {}2199 2200  /// See AbstractAttribute::initialize(...).2201  void initialize(Attributor &A) override {2202    bool IsKnown;2203    assert(!AA::hasAssumedIRAttr<Attribute::NoSync>(A, nullptr, getIRPosition(),2204                                                    DepClassTy::NONE, IsKnown));2205    (void)IsKnown;2206  }2207 2208  const std::string getAsStr(Attributor *A) const override {2209    return getAssumed() ? "nosync" : "may-sync";2210  }2211 2212  /// See AbstractAttribute::updateImpl(...).2213  ChangeStatus updateImpl(Attributor &A) override;2214};2215 2216ChangeStatus AANoSyncImpl::updateImpl(Attributor &A) {2217 2218  auto CheckRWInstForNoSync = [&](Instruction &I) {2219    return AA::isNoSyncInst(A, I, *this);2220  };2221 2222  auto CheckForNoSync = [&](Instruction &I) {2223    // At this point we handled all read/write effects and they are all2224    // nosync, so they can be skipped.2225    if (I.mayReadOrWriteMemory())2226      return true;2227 2228    bool IsKnown;2229    CallBase &CB = cast<CallBase>(I);2230    if (AA::hasAssumedIRAttr<Attribute::NoSync>(2231            A, this, IRPosition::callsite_function(CB), DepClassTy::OPTIONAL,2232            IsKnown))2233      return true;2234 2235    // non-convergent and readnone imply nosync.2236    return !CB.isConvergent();2237  };2238 2239  bool UsedAssumedInformation = false;2240  if (!A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *this,2241                                          UsedAssumedInformation) ||2242      !A.checkForAllCallLikeInstructions(CheckForNoSync, *this,2243                                         UsedAssumedInformation))2244    return indicatePessimisticFixpoint();2245 2246  return ChangeStatus::UNCHANGED;2247}2248 2249struct AANoSyncFunction final : public AANoSyncImpl {2250  AANoSyncFunction(const IRPosition &IRP, Attributor &A)2251      : AANoSyncImpl(IRP, A) {}2252 2253  /// See AbstractAttribute::trackStatistics()2254  void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nosync) }2255};2256 2257/// NoSync attribute deduction for a call sites.2258struct AANoSyncCallSite final : AACalleeToCallSite<AANoSync, AANoSyncImpl> {2259  AANoSyncCallSite(const IRPosition &IRP, Attributor &A)2260      : AACalleeToCallSite<AANoSync, AANoSyncImpl>(IRP, A) {}2261 2262  /// See AbstractAttribute::trackStatistics()2263  void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nosync); }2264};2265} // namespace2266 2267/// ------------------------ No-Free Attributes ----------------------------2268 2269namespace {2270struct AANoFreeImpl : public AANoFree {2271  AANoFreeImpl(const IRPosition &IRP, Attributor &A) : AANoFree(IRP, A) {}2272 2273  /// See AbstractAttribute::initialize(...).2274  void initialize(Attributor &A) override {2275    bool IsKnown;2276    assert(!AA::hasAssumedIRAttr<Attribute::NoFree>(A, nullptr, getIRPosition(),2277                                                    DepClassTy::NONE, IsKnown));2278    (void)IsKnown;2279  }2280 2281  /// See AbstractAttribute::updateImpl(...).2282  ChangeStatus updateImpl(Attributor &A) override {2283    auto CheckForNoFree = [&](Instruction &I) {2284      bool IsKnown;2285      return AA::hasAssumedIRAttr<Attribute::NoFree>(2286          A, this, IRPosition::callsite_function(cast<CallBase>(I)),2287          DepClassTy::REQUIRED, IsKnown);2288    };2289 2290    bool UsedAssumedInformation = false;2291    if (!A.checkForAllCallLikeInstructions(CheckForNoFree, *this,2292                                           UsedAssumedInformation))2293      return indicatePessimisticFixpoint();2294    return ChangeStatus::UNCHANGED;2295  }2296 2297  /// See AbstractAttribute::getAsStr().2298  const std::string getAsStr(Attributor *A) const override {2299    return getAssumed() ? "nofree" : "may-free";2300  }2301};2302 2303struct AANoFreeFunction final : public AANoFreeImpl {2304  AANoFreeFunction(const IRPosition &IRP, Attributor &A)2305      : AANoFreeImpl(IRP, A) {}2306 2307  /// See AbstractAttribute::trackStatistics()2308  void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nofree) }2309};2310 2311/// NoFree attribute deduction for a call sites.2312struct AANoFreeCallSite final : AACalleeToCallSite<AANoFree, AANoFreeImpl> {2313  AANoFreeCallSite(const IRPosition &IRP, Attributor &A)2314      : AACalleeToCallSite<AANoFree, AANoFreeImpl>(IRP, A) {}2315 2316  /// See AbstractAttribute::trackStatistics()2317  void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nofree); }2318};2319 2320/// NoFree attribute for floating values.2321struct AANoFreeFloating : AANoFreeImpl {2322  AANoFreeFloating(const IRPosition &IRP, Attributor &A)2323      : AANoFreeImpl(IRP, A) {}2324 2325  /// See AbstractAttribute::trackStatistics()2326  void trackStatistics() const override{STATS_DECLTRACK_FLOATING_ATTR(nofree)}2327 2328  /// See Abstract Attribute::updateImpl(...).2329  ChangeStatus updateImpl(Attributor &A) override {2330    const IRPosition &IRP = getIRPosition();2331 2332    bool IsKnown;2333    if (AA::hasAssumedIRAttr<Attribute::NoFree>(A, this,2334                                                IRPosition::function_scope(IRP),2335                                                DepClassTy::OPTIONAL, IsKnown))2336      return ChangeStatus::UNCHANGED;2337 2338    Value &AssociatedValue = getIRPosition().getAssociatedValue();2339    auto Pred = [&](const Use &U, bool &Follow) -> bool {2340      Instruction *UserI = cast<Instruction>(U.getUser());2341      if (auto *CB = dyn_cast<CallBase>(UserI)) {2342        if (CB->isBundleOperand(&U))2343          return false;2344        if (!CB->isArgOperand(&U))2345          return true;2346        unsigned ArgNo = CB->getArgOperandNo(&U);2347 2348        bool IsKnown;2349        return AA::hasAssumedIRAttr<Attribute::NoFree>(2350            A, this, IRPosition::callsite_argument(*CB, ArgNo),2351            DepClassTy::REQUIRED, IsKnown);2352      }2353 2354      if (isa<GetElementPtrInst>(UserI) || isa<PHINode>(UserI) ||2355          isa<SelectInst>(UserI)) {2356        Follow = true;2357        return true;2358      }2359      if (isa<StoreInst>(UserI) || isa<LoadInst>(UserI))2360        return true;2361 2362      if (isa<ReturnInst>(UserI) && getIRPosition().isArgumentPosition())2363        return true;2364 2365      // Unknown user.2366      return false;2367    };2368    if (!A.checkForAllUses(Pred, *this, AssociatedValue))2369      return indicatePessimisticFixpoint();2370 2371    return ChangeStatus::UNCHANGED;2372  }2373};2374 2375/// NoFree attribute for a call site argument.2376struct AANoFreeArgument final : AANoFreeFloating {2377  AANoFreeArgument(const IRPosition &IRP, Attributor &A)2378      : AANoFreeFloating(IRP, A) {}2379 2380  /// See AbstractAttribute::trackStatistics()2381  void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nofree) }2382};2383 2384/// NoFree attribute for call site arguments.2385struct AANoFreeCallSiteArgument final : AANoFreeFloating {2386  AANoFreeCallSiteArgument(const IRPosition &IRP, Attributor &A)2387      : AANoFreeFloating(IRP, A) {}2388 2389  /// See AbstractAttribute::updateImpl(...).2390  ChangeStatus updateImpl(Attributor &A) override {2391    // TODO: Once we have call site specific value information we can provide2392    //       call site specific liveness information and then it makes2393    //       sense to specialize attributes for call sites arguments instead of2394    //       redirecting requests to the callee argument.2395    Argument *Arg = getAssociatedArgument();2396    if (!Arg)2397      return indicatePessimisticFixpoint();2398    const IRPosition &ArgPos = IRPosition::argument(*Arg);2399    bool IsKnown;2400    if (AA::hasAssumedIRAttr<Attribute::NoFree>(A, this, ArgPos,2401                                                DepClassTy::REQUIRED, IsKnown))2402      return ChangeStatus::UNCHANGED;2403    return indicatePessimisticFixpoint();2404  }2405 2406  /// See AbstractAttribute::trackStatistics()2407  void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(nofree) };2408};2409 2410/// NoFree attribute for function return value.2411struct AANoFreeReturned final : AANoFreeFloating {2412  AANoFreeReturned(const IRPosition &IRP, Attributor &A)2413      : AANoFreeFloating(IRP, A) {2414    llvm_unreachable("NoFree is not applicable to function returns!");2415  }2416 2417  /// See AbstractAttribute::initialize(...).2418  void initialize(Attributor &A) override {2419    llvm_unreachable("NoFree is not applicable to function returns!");2420  }2421 2422  /// See AbstractAttribute::updateImpl(...).2423  ChangeStatus updateImpl(Attributor &A) override {2424    llvm_unreachable("NoFree is not applicable to function returns!");2425  }2426 2427  /// See AbstractAttribute::trackStatistics()2428  void trackStatistics() const override {}2429};2430 2431/// NoFree attribute deduction for a call site return value.2432struct AANoFreeCallSiteReturned final : AANoFreeFloating {2433  AANoFreeCallSiteReturned(const IRPosition &IRP, Attributor &A)2434      : AANoFreeFloating(IRP, A) {}2435 2436  ChangeStatus manifest(Attributor &A) override {2437    return ChangeStatus::UNCHANGED;2438  }2439  /// See AbstractAttribute::trackStatistics()2440  void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(nofree) }2441};2442} // namespace2443 2444/// ------------------------ NonNull Argument Attribute ------------------------2445 2446bool AANonNull::isImpliedByIR(Attributor &A, const IRPosition &IRP,2447                              Attribute::AttrKind ImpliedAttributeKind,2448                              bool IgnoreSubsumingPositions) {2449  SmallVector<Attribute::AttrKind, 2> AttrKinds;2450  AttrKinds.push_back(Attribute::NonNull);2451  if (!NullPointerIsDefined(IRP.getAnchorScope(),2452                            IRP.getAssociatedType()->getPointerAddressSpace()))2453    AttrKinds.push_back(Attribute::Dereferenceable);2454  if (A.hasAttr(IRP, AttrKinds, IgnoreSubsumingPositions, Attribute::NonNull))2455    return true;2456 2457  DominatorTree *DT = nullptr;2458  AssumptionCache *AC = nullptr;2459  InformationCache &InfoCache = A.getInfoCache();2460  if (const Function *Fn = IRP.getAnchorScope()) {2461    if (!Fn->isDeclaration()) {2462      DT = InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*Fn);2463      AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*Fn);2464    }2465  }2466 2467  SmallVector<AA::ValueAndContext> Worklist;2468  if (IRP.getPositionKind() != IRP_RETURNED) {2469    Worklist.push_back({IRP.getAssociatedValue(), IRP.getCtxI()});2470  } else {2471    bool UsedAssumedInformation = false;2472    if (!A.checkForAllInstructions(2473            [&](Instruction &I) {2474              Worklist.push_back({*cast<ReturnInst>(I).getReturnValue(), &I});2475              return true;2476            },2477            IRP.getAssociatedFunction(), nullptr, {Instruction::Ret},2478            UsedAssumedInformation, false, /*CheckPotentiallyDead=*/true))2479      return false;2480  }2481 2482  if (llvm::any_of(Worklist, [&](AA::ValueAndContext VAC) {2483        return !isKnownNonZero(2484            VAC.getValue(),2485            SimplifyQuery(A.getDataLayout(), DT, AC, VAC.getCtxI()));2486      }))2487    return false;2488 2489  A.manifestAttrs(IRP, {Attribute::get(IRP.getAnchorValue().getContext(),2490                                       Attribute::NonNull)});2491  return true;2492}2493 2494namespace {2495static int64_t getKnownNonNullAndDerefBytesForUse(2496    Attributor &A, const AbstractAttribute &QueryingAA, Value &AssociatedValue,2497    const Use *U, const Instruction *I, bool &IsNonNull, bool &TrackUse) {2498  TrackUse = false;2499 2500  const Value *UseV = U->get();2501  if (!UseV->getType()->isPointerTy())2502    return 0;2503 2504  // We need to follow common pointer manipulation uses to the accesses they2505  // feed into. We can try to be smart to avoid looking through things we do not2506  // like for now, e.g., non-inbounds GEPs.2507  if (isa<CastInst>(I)) {2508    TrackUse = true;2509    return 0;2510  }2511 2512  if (isa<GetElementPtrInst>(I)) {2513    TrackUse = true;2514    return 0;2515  }2516 2517  Type *PtrTy = UseV->getType();2518  const Function *F = I->getFunction();2519  bool NullPointerIsDefined =2520      F ? llvm::NullPointerIsDefined(F, PtrTy->getPointerAddressSpace()) : true;2521  const DataLayout &DL = A.getInfoCache().getDL();2522  if (const auto *CB = dyn_cast<CallBase>(I)) {2523    if (CB->isBundleOperand(U)) {2524      if (RetainedKnowledge RK = getKnowledgeFromUse(2525              U, {Attribute::NonNull, Attribute::Dereferenceable})) {2526        IsNonNull |=2527            (RK.AttrKind == Attribute::NonNull || !NullPointerIsDefined);2528        return RK.ArgValue;2529      }2530      return 0;2531    }2532 2533    if (CB->isCallee(U)) {2534      IsNonNull |= !NullPointerIsDefined;2535      return 0;2536    }2537 2538    unsigned ArgNo = CB->getArgOperandNo(U);2539    IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);2540    // As long as we only use known information there is no need to track2541    // dependences here.2542    bool IsKnownNonNull;2543    AA::hasAssumedIRAttr<Attribute::NonNull>(A, &QueryingAA, IRP,2544                                             DepClassTy::NONE, IsKnownNonNull);2545    IsNonNull |= IsKnownNonNull;2546    auto *DerefAA =2547        A.getAAFor<AADereferenceable>(QueryingAA, IRP, DepClassTy::NONE);2548    return DerefAA ? DerefAA->getKnownDereferenceableBytes() : 0;2549  }2550 2551  std::optional<MemoryLocation> Loc = MemoryLocation::getOrNone(I);2552  if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() ||2553      Loc->Size.isScalable() || I->isVolatile())2554    return 0;2555 2556  int64_t Offset;2557  const Value *Base =2558      getMinimalBaseOfPointer(A, QueryingAA, Loc->Ptr, Offset, DL);2559  if (Base && Base == &AssociatedValue) {2560    int64_t DerefBytes = Loc->Size.getValue() + Offset;2561    IsNonNull |= !NullPointerIsDefined;2562    return std::max(int64_t(0), DerefBytes);2563  }2564 2565  /// Corner case when an offset is 0.2566  Base = GetPointerBaseWithConstantOffset(Loc->Ptr, Offset, DL,2567                                          /*AllowNonInbounds*/ true);2568  if (Base && Base == &AssociatedValue && Offset == 0) {2569    int64_t DerefBytes = Loc->Size.getValue();2570    IsNonNull |= !NullPointerIsDefined;2571    return std::max(int64_t(0), DerefBytes);2572  }2573 2574  return 0;2575}2576 2577struct AANonNullImpl : AANonNull {2578  AANonNullImpl(const IRPosition &IRP, Attributor &A) : AANonNull(IRP, A) {}2579 2580  /// See AbstractAttribute::initialize(...).2581  void initialize(Attributor &A) override {2582    Value &V = *getAssociatedValue().stripPointerCasts();2583    if (isa<ConstantPointerNull>(V)) {2584      indicatePessimisticFixpoint();2585      return;2586    }2587 2588    if (Instruction *CtxI = getCtxI())2589      followUsesInMBEC(*this, A, getState(), *CtxI);2590  }2591 2592  /// See followUsesInMBEC2593  bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,2594                       AANonNull::StateType &State) {2595    bool IsNonNull = false;2596    bool TrackUse = false;2597    getKnownNonNullAndDerefBytesForUse(A, *this, getAssociatedValue(), U, I,2598                                       IsNonNull, TrackUse);2599    State.setKnown(IsNonNull);2600    return TrackUse;2601  }2602 2603  /// See AbstractAttribute::getAsStr().2604  const std::string getAsStr(Attributor *A) const override {2605    return getAssumed() ? "nonnull" : "may-null";2606  }2607};2608 2609/// NonNull attribute for a floating value.2610struct AANonNullFloating : public AANonNullImpl {2611  AANonNullFloating(const IRPosition &IRP, Attributor &A)2612      : AANonNullImpl(IRP, A) {}2613 2614  /// See AbstractAttribute::updateImpl(...).2615  ChangeStatus updateImpl(Attributor &A) override {2616    auto CheckIRP = [&](const IRPosition &IRP) {2617      bool IsKnownNonNull;2618      return AA::hasAssumedIRAttr<Attribute::NonNull>(2619          A, *this, IRP, DepClassTy::OPTIONAL, IsKnownNonNull);2620    };2621 2622    bool Stripped;2623    bool UsedAssumedInformation = false;2624    Value *AssociatedValue = &getAssociatedValue();2625    SmallVector<AA::ValueAndContext> Values;2626    if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,2627                                      AA::AnyScope, UsedAssumedInformation))2628      Stripped = false;2629    else2630      Stripped =2631          Values.size() != 1 || Values.front().getValue() != AssociatedValue;2632 2633    if (!Stripped) {2634      bool IsKnown;2635      if (auto *PHI = dyn_cast<PHINode>(AssociatedValue))2636        if (llvm::all_of(PHI->incoming_values(), [&](Value *Op) {2637              return AA::hasAssumedIRAttr<Attribute::NonNull>(2638                  A, this, IRPosition::value(*Op), DepClassTy::OPTIONAL,2639                  IsKnown);2640            }))2641          return ChangeStatus::UNCHANGED;2642      if (auto *Select = dyn_cast<SelectInst>(AssociatedValue))2643        if (AA::hasAssumedIRAttr<Attribute::NonNull>(2644                A, this, IRPosition::value(*Select->getFalseValue()),2645                DepClassTy::OPTIONAL, IsKnown) &&2646            AA::hasAssumedIRAttr<Attribute::NonNull>(2647                A, this, IRPosition::value(*Select->getTrueValue()),2648                DepClassTy::OPTIONAL, IsKnown))2649          return ChangeStatus::UNCHANGED;2650 2651      // If we haven't stripped anything we might still be able to use a2652      // different AA, but only if the IRP changes. Effectively when we2653      // interpret this not as a call site value but as a floating/argument2654      // value.2655      const IRPosition AVIRP = IRPosition::value(*AssociatedValue);2656      if (AVIRP == getIRPosition() || !CheckIRP(AVIRP))2657        return indicatePessimisticFixpoint();2658      return ChangeStatus::UNCHANGED;2659    }2660 2661    for (const auto &VAC : Values)2662      if (!CheckIRP(IRPosition::value(*VAC.getValue())))2663        return indicatePessimisticFixpoint();2664 2665    return ChangeStatus::UNCHANGED;2666  }2667 2668  /// See AbstractAttribute::trackStatistics()2669  void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) }2670};2671 2672/// NonNull attribute for function return value.2673struct AANonNullReturned final2674    : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,2675                                   false, AANonNull::IRAttributeKind, false> {2676  AANonNullReturned(const IRPosition &IRP, Attributor &A)2677      : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,2678                                     false, Attribute::NonNull, false>(IRP, A) {2679  }2680 2681  /// See AbstractAttribute::getAsStr().2682  const std::string getAsStr(Attributor *A) const override {2683    return getAssumed() ? "nonnull" : "may-null";2684  }2685 2686  /// See AbstractAttribute::trackStatistics()2687  void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) }2688};2689 2690/// NonNull attribute for function argument.2691struct AANonNullArgument final2692    : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl> {2693  AANonNullArgument(const IRPosition &IRP, Attributor &A)2694      : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl>(IRP, A) {}2695 2696  /// See AbstractAttribute::trackStatistics()2697  void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nonnull) }2698};2699 2700struct AANonNullCallSiteArgument final : AANonNullFloating {2701  AANonNullCallSiteArgument(const IRPosition &IRP, Attributor &A)2702      : AANonNullFloating(IRP, A) {}2703 2704  /// See AbstractAttribute::trackStatistics()2705  void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(nonnull) }2706};2707 2708/// NonNull attribute for a call site return position.2709struct AANonNullCallSiteReturned final2710    : AACalleeToCallSite<AANonNull, AANonNullImpl> {2711  AANonNullCallSiteReturned(const IRPosition &IRP, Attributor &A)2712      : AACalleeToCallSite<AANonNull, AANonNullImpl>(IRP, A) {}2713 2714  /// See AbstractAttribute::trackStatistics()2715  void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(nonnull) }2716};2717} // namespace2718 2719/// ------------------------ Must-Progress Attributes --------------------------2720namespace {2721struct AAMustProgressImpl : public AAMustProgress {2722  AAMustProgressImpl(const IRPosition &IRP, Attributor &A)2723      : AAMustProgress(IRP, A) {}2724 2725  /// See AbstractAttribute::initialize(...).2726  void initialize(Attributor &A) override {2727    bool IsKnown;2728    assert(!AA::hasAssumedIRAttr<Attribute::MustProgress>(2729        A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));2730    (void)IsKnown;2731  }2732 2733  /// See AbstractAttribute::getAsStr()2734  const std::string getAsStr(Attributor *A) const override {2735    return getAssumed() ? "mustprogress" : "may-not-progress";2736  }2737};2738 2739struct AAMustProgressFunction final : AAMustProgressImpl {2740  AAMustProgressFunction(const IRPosition &IRP, Attributor &A)2741      : AAMustProgressImpl(IRP, A) {}2742 2743  /// See AbstractAttribute::updateImpl(...).2744  ChangeStatus updateImpl(Attributor &A) override {2745    bool IsKnown;2746    if (AA::hasAssumedIRAttr<Attribute::WillReturn>(2747            A, this, getIRPosition(), DepClassTy::OPTIONAL, IsKnown)) {2748      if (IsKnown)2749        return indicateOptimisticFixpoint();2750      return ChangeStatus::UNCHANGED;2751    }2752 2753    auto CheckForMustProgress = [&](AbstractCallSite ACS) {2754      IRPosition IPos = IRPosition::callsite_function(*ACS.getInstruction());2755      bool IsKnownMustProgress;2756      return AA::hasAssumedIRAttr<Attribute::MustProgress>(2757          A, this, IPos, DepClassTy::REQUIRED, IsKnownMustProgress,2758          /* IgnoreSubsumingPositions */ true);2759    };2760 2761    bool AllCallSitesKnown = true;2762    if (!A.checkForAllCallSites(CheckForMustProgress, *this,2763                                /* RequireAllCallSites */ true,2764                                AllCallSitesKnown))2765      return indicatePessimisticFixpoint();2766 2767    return ChangeStatus::UNCHANGED;2768  }2769 2770  /// See AbstractAttribute::trackStatistics()2771  void trackStatistics() const override {2772    STATS_DECLTRACK_FN_ATTR(mustprogress)2773  }2774};2775 2776/// MustProgress attribute deduction for a call sites.2777struct AAMustProgressCallSite final : AAMustProgressImpl {2778  AAMustProgressCallSite(const IRPosition &IRP, Attributor &A)2779      : AAMustProgressImpl(IRP, A) {}2780 2781  /// See AbstractAttribute::updateImpl(...).2782  ChangeStatus updateImpl(Attributor &A) override {2783    // TODO: Once we have call site specific value information we can provide2784    //       call site specific liveness information and then it makes2785    //       sense to specialize attributes for call sites arguments instead of2786    //       redirecting requests to the callee argument.2787    const IRPosition &FnPos = IRPosition::function(*getAnchorScope());2788    bool IsKnownMustProgress;2789    if (!AA::hasAssumedIRAttr<Attribute::MustProgress>(2790            A, this, FnPos, DepClassTy::REQUIRED, IsKnownMustProgress))2791      return indicatePessimisticFixpoint();2792    return ChangeStatus::UNCHANGED;2793  }2794 2795  /// See AbstractAttribute::trackStatistics()2796  void trackStatistics() const override {2797    STATS_DECLTRACK_CS_ATTR(mustprogress);2798  }2799};2800} // namespace2801 2802/// ------------------------ No-Recurse Attributes ----------------------------2803 2804namespace {2805struct AANoRecurseImpl : public AANoRecurse {2806  AANoRecurseImpl(const IRPosition &IRP, Attributor &A) : AANoRecurse(IRP, A) {}2807 2808  /// See AbstractAttribute::initialize(...).2809  void initialize(Attributor &A) override {2810    bool IsKnown;2811    assert(!AA::hasAssumedIRAttr<Attribute::NoRecurse>(2812        A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));2813    (void)IsKnown;2814  }2815 2816  /// See AbstractAttribute::getAsStr()2817  const std::string getAsStr(Attributor *A) const override {2818    return getAssumed() ? "norecurse" : "may-recurse";2819  }2820};2821 2822struct AANoRecurseFunction final : AANoRecurseImpl {2823  AANoRecurseFunction(const IRPosition &IRP, Attributor &A)2824      : AANoRecurseImpl(IRP, A) {}2825 2826  /// See AbstractAttribute::updateImpl(...).2827  ChangeStatus updateImpl(Attributor &A) override {2828 2829    // If all live call sites are known to be no-recurse, we are as well.2830    auto CallSitePred = [&](AbstractCallSite ACS) {2831      bool IsKnownNoRecurse;2832      if (!AA::hasAssumedIRAttr<Attribute::NoRecurse>(2833              A, this,2834              IRPosition::function(*ACS.getInstruction()->getFunction()),2835              DepClassTy::NONE, IsKnownNoRecurse))2836        return false;2837      return IsKnownNoRecurse;2838    };2839    bool UsedAssumedInformation = false;2840    if (A.checkForAllCallSites(CallSitePred, *this, true,2841                               UsedAssumedInformation)) {2842      // If we know all call sites and all are known no-recurse, we are done.2843      // If all known call sites, which might not be all that exist, are known2844      // to be no-recurse, we are not done but we can continue to assume2845      // no-recurse. If one of the call sites we have not visited will become2846      // live, another update is triggered.2847      if (!UsedAssumedInformation)2848        indicateOptimisticFixpoint();2849      return ChangeStatus::UNCHANGED;2850    }2851 2852    const AAInterFnReachability *EdgeReachability =2853        A.getAAFor<AAInterFnReachability>(*this, getIRPosition(),2854                                          DepClassTy::REQUIRED);2855    if (EdgeReachability && EdgeReachability->canReach(A, *getAnchorScope()))2856      return indicatePessimisticFixpoint();2857    return ChangeStatus::UNCHANGED;2858  }2859 2860  void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(norecurse) }2861};2862 2863/// NoRecurse attribute deduction for a call sites.2864struct AANoRecurseCallSite final2865    : AACalleeToCallSite<AANoRecurse, AANoRecurseImpl> {2866  AANoRecurseCallSite(const IRPosition &IRP, Attributor &A)2867      : AACalleeToCallSite<AANoRecurse, AANoRecurseImpl>(IRP, A) {}2868 2869  /// See AbstractAttribute::trackStatistics()2870  void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(norecurse); }2871};2872} // namespace2873 2874/// ------------------------ No-Convergent Attribute --------------------------2875 2876namespace {2877struct AANonConvergentImpl : public AANonConvergent {2878  AANonConvergentImpl(const IRPosition &IRP, Attributor &A)2879      : AANonConvergent(IRP, A) {}2880 2881  /// See AbstractAttribute::getAsStr()2882  const std::string getAsStr(Attributor *A) const override {2883    return getAssumed() ? "non-convergent" : "may-be-convergent";2884  }2885};2886 2887struct AANonConvergentFunction final : AANonConvergentImpl {2888  AANonConvergentFunction(const IRPosition &IRP, Attributor &A)2889      : AANonConvergentImpl(IRP, A) {}2890 2891  /// See AbstractAttribute::updateImpl(...).2892  ChangeStatus updateImpl(Attributor &A) override {2893    // If all function calls are known to not be convergent, we are not2894    // convergent.2895    auto CalleeIsNotConvergent = [&](Instruction &Inst) {2896      CallBase &CB = cast<CallBase>(Inst);2897      auto *Callee = dyn_cast_if_present<Function>(CB.getCalledOperand());2898      if (!Callee || Callee->isIntrinsic()) {2899        return false;2900      }2901      if (Callee->isDeclaration()) {2902        return !Callee->hasFnAttribute(Attribute::Convergent);2903      }2904      const auto *ConvergentAA = A.getAAFor<AANonConvergent>(2905          *this, IRPosition::function(*Callee), DepClassTy::REQUIRED);2906      return ConvergentAA && ConvergentAA->isAssumedNotConvergent();2907    };2908 2909    bool UsedAssumedInformation = false;2910    if (!A.checkForAllCallLikeInstructions(CalleeIsNotConvergent, *this,2911                                           UsedAssumedInformation)) {2912      return indicatePessimisticFixpoint();2913    }2914    return ChangeStatus::UNCHANGED;2915  }2916 2917  ChangeStatus manifest(Attributor &A) override {2918    if (isKnownNotConvergent() &&2919        A.hasAttr(getIRPosition(), Attribute::Convergent)) {2920      A.removeAttrs(getIRPosition(), {Attribute::Convergent});2921      return ChangeStatus::CHANGED;2922    }2923    return ChangeStatus::UNCHANGED;2924  }2925 2926  void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(convergent) }2927};2928} // namespace2929 2930/// -------------------- Undefined-Behavior Attributes ------------------------2931 2932namespace {2933struct AAUndefinedBehaviorImpl : public AAUndefinedBehavior {2934  AAUndefinedBehaviorImpl(const IRPosition &IRP, Attributor &A)2935      : AAUndefinedBehavior(IRP, A) {}2936 2937  /// See AbstractAttribute::updateImpl(...).2938  // through a pointer (i.e. also branches etc.)2939  ChangeStatus updateImpl(Attributor &A) override {2940    const size_t UBPrevSize = KnownUBInsts.size();2941    const size_t NoUBPrevSize = AssumedNoUBInsts.size();2942 2943    auto InspectMemAccessInstForUB = [&](Instruction &I) {2944      // Lang ref now states volatile store is not UB, let's skip them.2945      if (I.isVolatile() && I.mayWriteToMemory())2946        return true;2947 2948      // Skip instructions that are already saved.2949      if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))2950        return true;2951 2952      // If we reach here, we know we have an instruction2953      // that accesses memory through a pointer operand,2954      // for which getPointerOperand() should give it to us.2955      Value *PtrOp =2956          const_cast<Value *>(getPointerOperand(&I, /* AllowVolatile */ true));2957      assert(PtrOp &&2958             "Expected pointer operand of memory accessing instruction");2959 2960      // Either we stopped and the appropriate action was taken,2961      // or we got back a simplified value to continue.2962      std::optional<Value *> SimplifiedPtrOp =2963          stopOnUndefOrAssumed(A, PtrOp, &I);2964      if (!SimplifiedPtrOp || !*SimplifiedPtrOp)2965        return true;2966      const Value *PtrOpVal = *SimplifiedPtrOp;2967 2968      // A memory access through a pointer is considered UB2969      // only if the pointer has constant null value.2970      // TODO: Expand it to not only check constant values.2971      if (!isa<ConstantPointerNull>(PtrOpVal)) {2972        AssumedNoUBInsts.insert(&I);2973        return true;2974      }2975      const Type *PtrTy = PtrOpVal->getType();2976 2977      // Because we only consider instructions inside functions,2978      // assume that a parent function exists.2979      const Function *F = I.getFunction();2980 2981      // A memory access using constant null pointer is only considered UB2982      // if null pointer is _not_ defined for the target platform.2983      if (llvm::NullPointerIsDefined(F, PtrTy->getPointerAddressSpace()))2984        AssumedNoUBInsts.insert(&I);2985      else2986        KnownUBInsts.insert(&I);2987      return true;2988    };2989 2990    auto InspectBrInstForUB = [&](Instruction &I) {2991      // A conditional branch instruction is considered UB if it has `undef`2992      // condition.2993 2994      // Skip instructions that are already saved.2995      if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))2996        return true;2997 2998      // We know we have a branch instruction.2999      auto *BrInst = cast<BranchInst>(&I);3000 3001      // Unconditional branches are never considered UB.3002      if (BrInst->isUnconditional())3003        return true;3004 3005      // Either we stopped and the appropriate action was taken,3006      // or we got back a simplified value to continue.3007      std::optional<Value *> SimplifiedCond =3008          stopOnUndefOrAssumed(A, BrInst->getCondition(), BrInst);3009      if (!SimplifiedCond || !*SimplifiedCond)3010        return true;3011      AssumedNoUBInsts.insert(&I);3012      return true;3013    };3014 3015    auto InspectCallSiteForUB = [&](Instruction &I) {3016      // Check whether a callsite always cause UB or not3017 3018      // Skip instructions that are already saved.3019      if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))3020        return true;3021 3022      // Check nonnull and noundef argument attribute violation for each3023      // callsite.3024      CallBase &CB = cast<CallBase>(I);3025      auto *Callee = dyn_cast_if_present<Function>(CB.getCalledOperand());3026      if (!Callee)3027        return true;3028      for (unsigned idx = 0; idx < CB.arg_size(); idx++) {3029        // If current argument is known to be simplified to null pointer and the3030        // corresponding argument position is known to have nonnull attribute,3031        // the argument is poison. Furthermore, if the argument is poison and3032        // the position is known to have noundef attriubte, this callsite is3033        // considered UB.3034        if (idx >= Callee->arg_size())3035          break;3036        Value *ArgVal = CB.getArgOperand(idx);3037        if (!ArgVal)3038          continue;3039        // Here, we handle three cases.3040        //   (1) Not having a value means it is dead. (we can replace the value3041        //       with undef)3042        //   (2) Simplified to undef. The argument violate noundef attriubte.3043        //   (3) Simplified to null pointer where known to be nonnull.3044        //       The argument is a poison value and violate noundef attribute.3045        IRPosition CalleeArgumentIRP = IRPosition::callsite_argument(CB, idx);3046        bool IsKnownNoUndef;3047        AA::hasAssumedIRAttr<Attribute::NoUndef>(3048            A, this, CalleeArgumentIRP, DepClassTy::NONE, IsKnownNoUndef);3049        if (!IsKnownNoUndef)3050          continue;3051        bool UsedAssumedInformation = false;3052        std::optional<Value *> SimplifiedVal =3053            A.getAssumedSimplified(IRPosition::value(*ArgVal), *this,3054                                   UsedAssumedInformation, AA::Interprocedural);3055        if (UsedAssumedInformation)3056          continue;3057        if (SimplifiedVal && !*SimplifiedVal)3058          return true;3059        if (!SimplifiedVal || isa<UndefValue>(**SimplifiedVal)) {3060          KnownUBInsts.insert(&I);3061          continue;3062        }3063        if (!ArgVal->getType()->isPointerTy() ||3064            !isa<ConstantPointerNull>(**SimplifiedVal))3065          continue;3066        bool IsKnownNonNull;3067        AA::hasAssumedIRAttr<Attribute::NonNull>(3068            A, this, CalleeArgumentIRP, DepClassTy::NONE, IsKnownNonNull);3069        if (IsKnownNonNull)3070          KnownUBInsts.insert(&I);3071      }3072      return true;3073    };3074 3075    auto InspectReturnInstForUB = [&](Instruction &I) {3076      auto &RI = cast<ReturnInst>(I);3077      // Either we stopped and the appropriate action was taken,3078      // or we got back a simplified return value to continue.3079      std::optional<Value *> SimplifiedRetValue =3080          stopOnUndefOrAssumed(A, RI.getReturnValue(), &I);3081      if (!SimplifiedRetValue || !*SimplifiedRetValue)3082        return true;3083 3084      // Check if a return instruction always cause UB or not3085      // Note: It is guaranteed that the returned position of the anchor3086      //       scope has noundef attribute when this is called.3087      //       We also ensure the return position is not "assumed dead"3088      //       because the returned value was then potentially simplified to3089      //       `undef` in AAReturnedValues without removing the `noundef`3090      //       attribute yet.3091 3092      // When the returned position has noundef attriubte, UB occurs in the3093      // following cases.3094      //   (1) Returned value is known to be undef.3095      //   (2) The value is known to be a null pointer and the returned3096      //       position has nonnull attribute (because the returned value is3097      //       poison).3098      if (isa<ConstantPointerNull>(*SimplifiedRetValue)) {3099        bool IsKnownNonNull;3100        AA::hasAssumedIRAttr<Attribute::NonNull>(3101            A, this, IRPosition::returned(*getAnchorScope()), DepClassTy::NONE,3102            IsKnownNonNull);3103        if (IsKnownNonNull)3104          KnownUBInsts.insert(&I);3105      }3106 3107      return true;3108    };3109 3110    bool UsedAssumedInformation = false;3111    A.checkForAllInstructions(InspectMemAccessInstForUB, *this,3112                              {Instruction::Load, Instruction::Store,3113                               Instruction::AtomicCmpXchg,3114                               Instruction::AtomicRMW},3115                              UsedAssumedInformation,3116                              /* CheckBBLivenessOnly */ true);3117    A.checkForAllInstructions(InspectBrInstForUB, *this, {Instruction::Br},3118                              UsedAssumedInformation,3119                              /* CheckBBLivenessOnly */ true);3120    A.checkForAllCallLikeInstructions(InspectCallSiteForUB, *this,3121                                      UsedAssumedInformation);3122 3123    // If the returned position of the anchor scope has noundef attriubte, check3124    // all returned instructions.3125    if (!getAnchorScope()->getReturnType()->isVoidTy()) {3126      const IRPosition &ReturnIRP = IRPosition::returned(*getAnchorScope());3127      if (!A.isAssumedDead(ReturnIRP, this, nullptr, UsedAssumedInformation)) {3128        bool IsKnownNoUndef;3129        AA::hasAssumedIRAttr<Attribute::NoUndef>(3130            A, this, ReturnIRP, DepClassTy::NONE, IsKnownNoUndef);3131        if (IsKnownNoUndef)3132          A.checkForAllInstructions(InspectReturnInstForUB, *this,3133                                    {Instruction::Ret}, UsedAssumedInformation,3134                                    /* CheckBBLivenessOnly */ true);3135      }3136    }3137 3138    if (NoUBPrevSize != AssumedNoUBInsts.size() ||3139        UBPrevSize != KnownUBInsts.size())3140      return ChangeStatus::CHANGED;3141    return ChangeStatus::UNCHANGED;3142  }3143 3144  bool isKnownToCauseUB(Instruction *I) const override {3145    return KnownUBInsts.count(I);3146  }3147 3148  bool isAssumedToCauseUB(Instruction *I) const override {3149    // In simple words, if an instruction is not in the assumed to _not_3150    // cause UB, then it is assumed UB (that includes those3151    // in the KnownUBInsts set). The rest is boilerplate3152    // is to ensure that it is one of the instructions we test3153    // for UB.3154 3155    switch (I->getOpcode()) {3156    case Instruction::Load:3157    case Instruction::Store:3158    case Instruction::AtomicCmpXchg:3159    case Instruction::AtomicRMW:3160      return !AssumedNoUBInsts.count(I);3161    case Instruction::Br: {3162      auto *BrInst = cast<BranchInst>(I);3163      if (BrInst->isUnconditional())3164        return false;3165      return !AssumedNoUBInsts.count(I);3166    } break;3167    default:3168      return false;3169    }3170    return false;3171  }3172 3173  ChangeStatus manifest(Attributor &A) override {3174    if (KnownUBInsts.empty())3175      return ChangeStatus::UNCHANGED;3176    for (Instruction *I : KnownUBInsts)3177      A.changeToUnreachableAfterManifest(I);3178    return ChangeStatus::CHANGED;3179  }3180 3181  /// See AbstractAttribute::getAsStr()3182  const std::string getAsStr(Attributor *A) const override {3183    return getAssumed() ? "undefined-behavior" : "no-ub";3184  }3185 3186  /// Note: The correctness of this analysis depends on the fact that the3187  /// following 2 sets will stop changing after some point.3188  /// "Change" here means that their size changes.3189  /// The size of each set is monotonically increasing3190  /// (we only add items to them) and it is upper bounded by the number of3191  /// instructions in the processed function (we can never save more3192  /// elements in either set than this number). Hence, at some point,3193  /// they will stop increasing.3194  /// Consequently, at some point, both sets will have stopped3195  /// changing, effectively making the analysis reach a fixpoint.3196 3197  /// Note: These 2 sets are disjoint and an instruction can be considered3198  /// one of 3 things:3199  /// 1) Known to cause UB (AAUndefinedBehavior could prove it) and put it in3200  ///    the KnownUBInsts set.3201  /// 2) Assumed to cause UB (in every updateImpl, AAUndefinedBehavior3202  ///    has a reason to assume it).3203  /// 3) Assumed to not cause UB. very other instruction - AAUndefinedBehavior3204  ///    could not find a reason to assume or prove that it can cause UB,3205  ///    hence it assumes it doesn't. We have a set for these instructions3206  ///    so that we don't reprocess them in every update.3207  ///    Note however that instructions in this set may cause UB.3208 3209protected:3210  /// A set of all live instructions _known_ to cause UB.3211  SmallPtrSet<Instruction *, 8> KnownUBInsts;3212 3213private:3214  /// A set of all the (live) instructions that are assumed to _not_ cause UB.3215  SmallPtrSet<Instruction *, 8> AssumedNoUBInsts;3216 3217  // Should be called on updates in which if we're processing an instruction3218  // \p I that depends on a value \p V, one of the following has to happen:3219  // - If the value is assumed, then stop.3220  // - If the value is known but undef, then consider it UB.3221  // - Otherwise, do specific processing with the simplified value.3222  // We return std::nullopt in the first 2 cases to signify that an appropriate3223  // action was taken and the caller should stop.3224  // Otherwise, we return the simplified value that the caller should3225  // use for specific processing.3226  std::optional<Value *> stopOnUndefOrAssumed(Attributor &A, Value *V,3227                                              Instruction *I) {3228    bool UsedAssumedInformation = false;3229    std::optional<Value *> SimplifiedV =3230        A.getAssumedSimplified(IRPosition::value(*V), *this,3231                               UsedAssumedInformation, AA::Interprocedural);3232    if (!UsedAssumedInformation) {3233      // Don't depend on assumed values.3234      if (!SimplifiedV) {3235        // If it is known (which we tested above) but it doesn't have a value,3236        // then we can assume `undef` and hence the instruction is UB.3237        KnownUBInsts.insert(I);3238        return std::nullopt;3239      }3240      if (!*SimplifiedV)3241        return nullptr;3242      V = *SimplifiedV;3243    }3244    if (isa<UndefValue>(V)) {3245      KnownUBInsts.insert(I);3246      return std::nullopt;3247    }3248    return V;3249  }3250};3251 3252struct AAUndefinedBehaviorFunction final : AAUndefinedBehaviorImpl {3253  AAUndefinedBehaviorFunction(const IRPosition &IRP, Attributor &A)3254      : AAUndefinedBehaviorImpl(IRP, A) {}3255 3256  /// See AbstractAttribute::trackStatistics()3257  void trackStatistics() const override {3258    STATS_DECL(UndefinedBehaviorInstruction, Instruction,3259               "Number of instructions known to have UB");3260    BUILD_STAT_NAME(UndefinedBehaviorInstruction, Instruction) +=3261        KnownUBInsts.size();3262  }3263};3264} // namespace3265 3266/// ------------------------ Will-Return Attributes ----------------------------3267 3268namespace {3269// Helper function that checks whether a function has any cycle which we don't3270// know if it is bounded or not.3271// Loops with maximum trip count are considered bounded, any other cycle not.3272static bool mayContainUnboundedCycle(Function &F, Attributor &A) {3273  ScalarEvolution *SE =3274      A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(F);3275  LoopInfo *LI = A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(F);3276  // If either SCEV or LoopInfo is not available for the function then we assume3277  // any cycle to be unbounded cycle.3278  // We use scc_iterator which uses Tarjan algorithm to find all the maximal3279  // SCCs.To detect if there's a cycle, we only need to find the maximal ones.3280  if (!SE || !LI) {3281    for (scc_iterator<Function *> SCCI = scc_begin(&F); !SCCI.isAtEnd(); ++SCCI)3282      if (SCCI.hasCycle())3283        return true;3284    return false;3285  }3286 3287  // If there's irreducible control, the function may contain non-loop cycles.3288  if (mayContainIrreducibleControl(F, LI))3289    return true;3290 3291  // Any loop that does not have a max trip count is considered unbounded cycle.3292  for (auto *L : LI->getLoopsInPreorder()) {3293    if (!SE->getSmallConstantMaxTripCount(L))3294      return true;3295  }3296  return false;3297}3298 3299struct AAWillReturnImpl : public AAWillReturn {3300  AAWillReturnImpl(const IRPosition &IRP, Attributor &A)3301      : AAWillReturn(IRP, A) {}3302 3303  /// See AbstractAttribute::initialize(...).3304  void initialize(Attributor &A) override {3305    bool IsKnown;3306    assert(!AA::hasAssumedIRAttr<Attribute::WillReturn>(3307        A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));3308    (void)IsKnown;3309  }3310 3311  /// Check for `mustprogress` and `readonly` as they imply `willreturn`.3312  bool isImpliedByMustprogressAndReadonly(Attributor &A, bool KnownOnly) {3313    if (!A.hasAttr(getIRPosition(), {Attribute::MustProgress}))3314      return false;3315 3316    bool IsKnown;3317    if (AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))3318      return IsKnown || !KnownOnly;3319    return false;3320  }3321 3322  /// See AbstractAttribute::updateImpl(...).3323  ChangeStatus updateImpl(Attributor &A) override {3324    if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ false))3325      return ChangeStatus::UNCHANGED;3326 3327    auto CheckForWillReturn = [&](Instruction &I) {3328      IRPosition IPos = IRPosition::callsite_function(cast<CallBase>(I));3329      bool IsKnown;3330      if (AA::hasAssumedIRAttr<Attribute::WillReturn>(3331              A, this, IPos, DepClassTy::REQUIRED, IsKnown)) {3332        if (IsKnown)3333          return true;3334      } else {3335        return false;3336      }3337      bool IsKnownNoRecurse;3338      return AA::hasAssumedIRAttr<Attribute::NoRecurse>(3339          A, this, IPos, DepClassTy::REQUIRED, IsKnownNoRecurse);3340    };3341 3342    bool UsedAssumedInformation = false;3343    if (!A.checkForAllCallLikeInstructions(CheckForWillReturn, *this,3344                                           UsedAssumedInformation))3345      return indicatePessimisticFixpoint();3346 3347    return ChangeStatus::UNCHANGED;3348  }3349 3350  /// See AbstractAttribute::getAsStr()3351  const std::string getAsStr(Attributor *A) const override {3352    return getAssumed() ? "willreturn" : "may-noreturn";3353  }3354};3355 3356struct AAWillReturnFunction final : AAWillReturnImpl {3357  AAWillReturnFunction(const IRPosition &IRP, Attributor &A)3358      : AAWillReturnImpl(IRP, A) {}3359 3360  /// See AbstractAttribute::initialize(...).3361  void initialize(Attributor &A) override {3362    AAWillReturnImpl::initialize(A);3363 3364    Function *F = getAnchorScope();3365    assert(F && "Did expect an anchor function");3366    if (F->isDeclaration() || mayContainUnboundedCycle(*F, A))3367      indicatePessimisticFixpoint();3368  }3369 3370  /// See AbstractAttribute::trackStatistics()3371  void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(willreturn) }3372};3373 3374/// WillReturn attribute deduction for a call sites.3375struct AAWillReturnCallSite final3376    : AACalleeToCallSite<AAWillReturn, AAWillReturnImpl> {3377  AAWillReturnCallSite(const IRPosition &IRP, Attributor &A)3378      : AACalleeToCallSite<AAWillReturn, AAWillReturnImpl>(IRP, A) {}3379 3380  /// See AbstractAttribute::updateImpl(...).3381  ChangeStatus updateImpl(Attributor &A) override {3382    if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ false))3383      return ChangeStatus::UNCHANGED;3384 3385    return AACalleeToCallSite::updateImpl(A);3386  }3387 3388  /// See AbstractAttribute::trackStatistics()3389  void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(willreturn); }3390};3391} // namespace3392 3393/// -------------------AAIntraFnReachability Attribute--------------------------3394 3395/// All information associated with a reachability query. This boilerplate code3396/// is used by both AAIntraFnReachability and AAInterFnReachability, with3397/// different \p ToTy values.3398template <typename ToTy> struct ReachabilityQueryInfo {3399  enum class Reachable {3400    No,3401    Yes,3402  };3403 3404  /// Start here,3405  const Instruction *From = nullptr;3406  /// reach this place,3407  const ToTy *To = nullptr;3408  /// without going through any of these instructions,3409  const AA::InstExclusionSetTy *ExclusionSet = nullptr;3410  /// and remember if it worked:3411  Reachable Result = Reachable::No;3412 3413  /// Precomputed hash for this RQI.3414  unsigned Hash = 0;3415 3416  unsigned computeHashValue() const {3417    assert(Hash == 0 && "Computed hash twice!");3418    using InstSetDMI = DenseMapInfo<const AA::InstExclusionSetTy *>;3419    using PairDMI = DenseMapInfo<std::pair<const Instruction *, const ToTy *>>;3420    return const_cast<ReachabilityQueryInfo<ToTy> *>(this)->Hash =3421               detail::combineHashValue(PairDMI ::getHashValue({From, To}),3422                                        InstSetDMI::getHashValue(ExclusionSet));3423  }3424 3425  ReachabilityQueryInfo(const Instruction *From, const ToTy *To)3426      : From(From), To(To) {}3427 3428  /// Constructor replacement to ensure unique and stable sets are used for the3429  /// cache.3430  ReachabilityQueryInfo(Attributor &A, const Instruction &From, const ToTy &To,3431                        const AA::InstExclusionSetTy *ES, bool MakeUnique)3432      : From(&From), To(&To), ExclusionSet(ES) {3433 3434    if (!ES || ES->empty()) {3435      ExclusionSet = nullptr;3436    } else if (MakeUnique) {3437      ExclusionSet = A.getInfoCache().getOrCreateUniqueBlockExecutionSet(ES);3438    }3439  }3440 3441  ReachabilityQueryInfo(const ReachabilityQueryInfo &RQI)3442      : From(RQI.From), To(RQI.To), ExclusionSet(RQI.ExclusionSet) {}3443};3444 3445namespace llvm {3446template <typename ToTy> struct DenseMapInfo<ReachabilityQueryInfo<ToTy> *> {3447  using InstSetDMI = DenseMapInfo<const AA::InstExclusionSetTy *>;3448  using PairDMI = DenseMapInfo<std::pair<const Instruction *, const ToTy *>>;3449 3450  static ReachabilityQueryInfo<ToTy> EmptyKey;3451  static ReachabilityQueryInfo<ToTy> TombstoneKey;3452 3453  static inline ReachabilityQueryInfo<ToTy> *getEmptyKey() { return &EmptyKey; }3454  static inline ReachabilityQueryInfo<ToTy> *getTombstoneKey() {3455    return &TombstoneKey;3456  }3457  static unsigned getHashValue(const ReachabilityQueryInfo<ToTy> *RQI) {3458    return RQI->Hash ? RQI->Hash : RQI->computeHashValue();3459  }3460  static bool isEqual(const ReachabilityQueryInfo<ToTy> *LHS,3461                      const ReachabilityQueryInfo<ToTy> *RHS) {3462    if (!PairDMI::isEqual({LHS->From, LHS->To}, {RHS->From, RHS->To}))3463      return false;3464    return InstSetDMI::isEqual(LHS->ExclusionSet, RHS->ExclusionSet);3465  }3466};3467 3468#define DefineKeys(ToTy)                                                       \3469  template <>                                                                  \3470  ReachabilityQueryInfo<ToTy>                                                  \3471      DenseMapInfo<ReachabilityQueryInfo<ToTy> *>::EmptyKey =                  \3472          ReachabilityQueryInfo<ToTy>(                                         \3473              DenseMapInfo<const Instruction *>::getEmptyKey(),                \3474              DenseMapInfo<const ToTy *>::getEmptyKey());                      \3475  template <>                                                                  \3476  ReachabilityQueryInfo<ToTy>                                                  \3477      DenseMapInfo<ReachabilityQueryInfo<ToTy> *>::TombstoneKey =              \3478          ReachabilityQueryInfo<ToTy>(                                         \3479              DenseMapInfo<const Instruction *>::getTombstoneKey(),            \3480              DenseMapInfo<const ToTy *>::getTombstoneKey());3481 3482DefineKeys(Instruction) DefineKeys(Function)3483#undef DefineKeys3484 3485} // namespace llvm3486 3487namespace {3488 3489template <typename BaseTy, typename ToTy>3490struct CachedReachabilityAA : public BaseTy {3491  using RQITy = ReachabilityQueryInfo<ToTy>;3492 3493  CachedReachabilityAA(const IRPosition &IRP, Attributor &A) : BaseTy(IRP, A) {}3494 3495  /// See AbstractAttribute::isQueryAA.3496  bool isQueryAA() const override { return true; }3497 3498  /// See AbstractAttribute::updateImpl(...).3499  ChangeStatus updateImpl(Attributor &A) override {3500    ChangeStatus Changed = ChangeStatus::UNCHANGED;3501    for (unsigned u = 0, e = QueryVector.size(); u < e; ++u) {3502      RQITy *RQI = QueryVector[u];3503      if (RQI->Result == RQITy::Reachable::No &&3504          isReachableImpl(A, *RQI, /*IsTemporaryRQI=*/false))3505        Changed = ChangeStatus::CHANGED;3506    }3507    return Changed;3508  }3509 3510  virtual bool isReachableImpl(Attributor &A, RQITy &RQI,3511                               bool IsTemporaryRQI) = 0;3512 3513  bool rememberResult(Attributor &A, typename RQITy::Reachable Result,3514                      RQITy &RQI, bool UsedExclusionSet, bool IsTemporaryRQI) {3515    RQI.Result = Result;3516 3517    // Remove the temporary RQI from the cache.3518    if (IsTemporaryRQI)3519      QueryCache.erase(&RQI);3520 3521    // Insert a plain RQI (w/o exclusion set) if that makes sense. Two options:3522    // 1) If it is reachable, it doesn't matter if we have an exclusion set for3523    // this query. 2) We did not use the exclusion set, potentially because3524    // there is none.3525    if (Result == RQITy::Reachable::Yes || !UsedExclusionSet) {3526      RQITy PlainRQI(RQI.From, RQI.To);3527      if (!QueryCache.count(&PlainRQI)) {3528        RQITy *RQIPtr = new (A.Allocator) RQITy(RQI.From, RQI.To);3529        RQIPtr->Result = Result;3530        QueryVector.push_back(RQIPtr);3531        QueryCache.insert(RQIPtr);3532      }3533    }3534 3535    // Check if we need to insert a new permanent RQI with the exclusion set.3536    if (IsTemporaryRQI && Result != RQITy::Reachable::Yes && UsedExclusionSet) {3537      assert((!RQI.ExclusionSet || !RQI.ExclusionSet->empty()) &&3538             "Did not expect empty set!");3539      RQITy *RQIPtr = new (A.Allocator)3540          RQITy(A, *RQI.From, *RQI.To, RQI.ExclusionSet, true);3541      assert(RQIPtr->Result == RQITy::Reachable::No && "Already reachable?");3542      RQIPtr->Result = Result;3543      assert(!QueryCache.count(RQIPtr));3544      QueryVector.push_back(RQIPtr);3545      QueryCache.insert(RQIPtr);3546    }3547 3548    if (Result == RQITy::Reachable::No && IsTemporaryRQI)3549      A.registerForUpdate(*this);3550    return Result == RQITy::Reachable::Yes;3551  }3552 3553  const std::string getAsStr(Attributor *A) const override {3554    // TODO: Return the number of reachable queries.3555    return "#queries(" + std::to_string(QueryVector.size()) + ")";3556  }3557 3558  bool checkQueryCache(Attributor &A, RQITy &StackRQI,3559                       typename RQITy::Reachable &Result) {3560    if (!this->getState().isValidState()) {3561      Result = RQITy::Reachable::Yes;3562      return true;3563    }3564 3565    // If we have an exclusion set we might be able to find our answer by3566    // ignoring it first.3567    if (StackRQI.ExclusionSet) {3568      RQITy PlainRQI(StackRQI.From, StackRQI.To);3569      auto It = QueryCache.find(&PlainRQI);3570      if (It != QueryCache.end() && (*It)->Result == RQITy::Reachable::No) {3571        Result = RQITy::Reachable::No;3572        return true;3573      }3574    }3575 3576    auto It = QueryCache.find(&StackRQI);3577    if (It != QueryCache.end()) {3578      Result = (*It)->Result;3579      return true;3580    }3581 3582    // Insert a temporary for recursive queries. We will replace it with a3583    // permanent entry later.3584    QueryCache.insert(&StackRQI);3585    return false;3586  }3587 3588private:3589  SmallVector<RQITy *> QueryVector;3590  DenseSet<RQITy *> QueryCache;3591};3592 3593struct AAIntraFnReachabilityFunction final3594    : public CachedReachabilityAA<AAIntraFnReachability, Instruction> {3595  using Base = CachedReachabilityAA<AAIntraFnReachability, Instruction>;3596  AAIntraFnReachabilityFunction(const IRPosition &IRP, Attributor &A)3597      : Base(IRP, A) {3598    DT = A.getInfoCache().getAnalysisResultForFunction<DominatorTreeAnalysis>(3599        *IRP.getAssociatedFunction());3600  }3601 3602  bool isAssumedReachable(3603      Attributor &A, const Instruction &From, const Instruction &To,3604      const AA::InstExclusionSetTy *ExclusionSet) const override {3605    auto *NonConstThis = const_cast<AAIntraFnReachabilityFunction *>(this);3606    if (&From == &To)3607      return true;3608 3609    RQITy StackRQI(A, From, To, ExclusionSet, false);3610    RQITy::Reachable Result;3611    if (!NonConstThis->checkQueryCache(A, StackRQI, Result))3612      return NonConstThis->isReachableImpl(A, StackRQI,3613                                           /*IsTemporaryRQI=*/true);3614    return Result == RQITy::Reachable::Yes;3615  }3616 3617  ChangeStatus updateImpl(Attributor &A) override {3618    // We only depend on liveness. DeadEdges is all we care about, check if any3619    // of them changed.3620    auto *LivenessAA =3621        A.getAAFor<AAIsDead>(*this, getIRPosition(), DepClassTy::OPTIONAL);3622    if (LivenessAA &&3623        llvm::all_of(DeadEdges,3624                     [&](const auto &DeadEdge) {3625                       return LivenessAA->isEdgeDead(DeadEdge.first,3626                                                     DeadEdge.second);3627                     }) &&3628        llvm::all_of(DeadBlocks, [&](const BasicBlock *BB) {3629          return LivenessAA->isAssumedDead(BB);3630        })) {3631      return ChangeStatus::UNCHANGED;3632    }3633    DeadEdges.clear();3634    DeadBlocks.clear();3635    return Base::updateImpl(A);3636  }3637 3638  bool isReachableImpl(Attributor &A, RQITy &RQI,3639                       bool IsTemporaryRQI) override {3640    const Instruction *Origin = RQI.From;3641    bool UsedExclusionSet = false;3642 3643    auto WillReachInBlock = [&](const Instruction &From, const Instruction &To,3644                                const AA::InstExclusionSetTy *ExclusionSet) {3645      const Instruction *IP = &From;3646      while (IP && IP != &To) {3647        if (ExclusionSet && IP != Origin && ExclusionSet->count(IP)) {3648          UsedExclusionSet = true;3649          break;3650        }3651        IP = IP->getNextNode();3652      }3653      return IP == &To;3654    };3655 3656    const BasicBlock *FromBB = RQI.From->getParent();3657    const BasicBlock *ToBB = RQI.To->getParent();3658    assert(FromBB->getParent() == ToBB->getParent() &&3659           "Not an intra-procedural query!");3660 3661    // Check intra-block reachability, however, other reaching paths are still3662    // possible.3663    if (FromBB == ToBB &&3664        WillReachInBlock(*RQI.From, *RQI.To, RQI.ExclusionSet))3665      return rememberResult(A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,3666                            IsTemporaryRQI);3667 3668    // Check if reaching the ToBB block is sufficient or if even that would not3669    // ensure reaching the target. In the latter case we are done.3670    if (!WillReachInBlock(ToBB->front(), *RQI.To, RQI.ExclusionSet))3671      return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet,3672                            IsTemporaryRQI);3673 3674    const Function *Fn = FromBB->getParent();3675    SmallPtrSet<const BasicBlock *, 16> ExclusionBlocks;3676    if (RQI.ExclusionSet)3677      for (auto *I : *RQI.ExclusionSet)3678        if (I->getFunction() == Fn)3679          ExclusionBlocks.insert(I->getParent());3680 3681    // Check if we make it out of the FromBB block at all.3682    if (ExclusionBlocks.count(FromBB) &&3683        !WillReachInBlock(*RQI.From, *FromBB->getTerminator(),3684                          RQI.ExclusionSet))3685      return rememberResult(A, RQITy::Reachable::No, RQI, true, IsTemporaryRQI);3686 3687    auto *LivenessAA =3688        A.getAAFor<AAIsDead>(*this, getIRPosition(), DepClassTy::OPTIONAL);3689    if (LivenessAA && LivenessAA->isAssumedDead(ToBB)) {3690      DeadBlocks.insert(ToBB);3691      return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet,3692                            IsTemporaryRQI);3693    }3694 3695    SmallPtrSet<const BasicBlock *, 16> Visited;3696    SmallVector<const BasicBlock *, 16> Worklist;3697    Worklist.push_back(FromBB);3698 3699    DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> LocalDeadEdges;3700    while (!Worklist.empty()) {3701      const BasicBlock *BB = Worklist.pop_back_val();3702      if (!Visited.insert(BB).second)3703        continue;3704      for (const BasicBlock *SuccBB : successors(BB)) {3705        if (LivenessAA && LivenessAA->isEdgeDead(BB, SuccBB)) {3706          LocalDeadEdges.insert({BB, SuccBB});3707          continue;3708        }3709        // We checked before if we just need to reach the ToBB block.3710        if (SuccBB == ToBB)3711          return rememberResult(A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,3712                                IsTemporaryRQI);3713        if (DT && ExclusionBlocks.empty() && DT->dominates(BB, ToBB))3714          return rememberResult(A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,3715                                IsTemporaryRQI);3716 3717        if (ExclusionBlocks.count(SuccBB)) {3718          UsedExclusionSet = true;3719          continue;3720        }3721        Worklist.push_back(SuccBB);3722      }3723    }3724 3725    DeadEdges.insert_range(LocalDeadEdges);3726    return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet,3727                          IsTemporaryRQI);3728  }3729 3730  /// See AbstractAttribute::trackStatistics()3731  void trackStatistics() const override {}3732 3733private:3734  // Set of assumed dead blocks we used in the last query. If any changes we3735  // update the state.3736  DenseSet<const BasicBlock *> DeadBlocks;3737 3738  // Set of assumed dead edges we used in the last query. If any changes we3739  // update the state.3740  DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> DeadEdges;3741 3742  /// The dominator tree of the function to short-circuit reasoning.3743  const DominatorTree *DT = nullptr;3744};3745} // namespace3746 3747/// ------------------------ NoAlias Argument Attribute ------------------------3748 3749bool AANoAlias::isImpliedByIR(Attributor &A, const IRPosition &IRP,3750                              Attribute::AttrKind ImpliedAttributeKind,3751                              bool IgnoreSubsumingPositions) {3752  assert(ImpliedAttributeKind == Attribute::NoAlias &&3753         "Unexpected attribute kind");3754  Value *Val = &IRP.getAssociatedValue();3755  if (IRP.getPositionKind() != IRP_CALL_SITE_ARGUMENT) {3756    if (isa<AllocaInst>(Val))3757      return true;3758  } else {3759    IgnoreSubsumingPositions = true;3760  }3761 3762  if (isa<UndefValue>(Val))3763    return true;3764 3765  if (isa<ConstantPointerNull>(Val) &&3766      !NullPointerIsDefined(IRP.getAnchorScope(),3767                            Val->getType()->getPointerAddressSpace()))3768    return true;3769 3770  if (A.hasAttr(IRP, {Attribute::ByVal, Attribute::NoAlias},3771                IgnoreSubsumingPositions, Attribute::NoAlias))3772    return true;3773 3774  return false;3775}3776 3777namespace {3778struct AANoAliasImpl : AANoAlias {3779  AANoAliasImpl(const IRPosition &IRP, Attributor &A) : AANoAlias(IRP, A) {3780    assert(getAssociatedType()->isPointerTy() &&3781           "Noalias is a pointer attribute");3782  }3783 3784  const std::string getAsStr(Attributor *A) const override {3785    return getAssumed() ? "noalias" : "may-alias";3786  }3787};3788 3789/// NoAlias attribute for a floating value.3790struct AANoAliasFloating final : AANoAliasImpl {3791  AANoAliasFloating(const IRPosition &IRP, Attributor &A)3792      : AANoAliasImpl(IRP, A) {}3793 3794  /// See AbstractAttribute::updateImpl(...).3795  ChangeStatus updateImpl(Attributor &A) override {3796    // TODO: Implement this.3797    return indicatePessimisticFixpoint();3798  }3799 3800  /// See AbstractAttribute::trackStatistics()3801  void trackStatistics() const override {3802    STATS_DECLTRACK_FLOATING_ATTR(noalias)3803  }3804};3805 3806/// NoAlias attribute for an argument.3807struct AANoAliasArgument final3808    : AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl> {3809  using Base = AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl>;3810  AANoAliasArgument(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}3811 3812  /// See AbstractAttribute::update(...).3813  ChangeStatus updateImpl(Attributor &A) override {3814    // We have to make sure no-alias on the argument does not break3815    // synchronization when this is a callback argument, see also [1] below.3816    // If synchronization cannot be affected, we delegate to the base updateImpl3817    // function, otherwise we give up for now.3818 3819    // If the function is no-sync, no-alias cannot break synchronization.3820    bool IsKnownNoSycn;3821    if (AA::hasAssumedIRAttr<Attribute::NoSync>(3822            A, this, IRPosition::function_scope(getIRPosition()),3823            DepClassTy::OPTIONAL, IsKnownNoSycn))3824      return Base::updateImpl(A);3825 3826    // If the argument is read-only, no-alias cannot break synchronization.3827    bool IsKnown;3828    if (AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))3829      return Base::updateImpl(A);3830 3831    // If the argument is never passed through callbacks, no-alias cannot break3832    // synchronization.3833    bool UsedAssumedInformation = false;3834    if (A.checkForAllCallSites(3835            [](AbstractCallSite ACS) { return !ACS.isCallbackCall(); }, *this,3836            true, UsedAssumedInformation))3837      return Base::updateImpl(A);3838 3839    // TODO: add no-alias but make sure it doesn't break synchronization by3840    // introducing fake uses. See:3841    // [1] Compiler Optimizations for OpenMP, J. Doerfert and H. Finkel,3842    //     International Workshop on OpenMP 2018,3843    //     http://compilers.cs.uni-saarland.de/people/doerfert/par_opt18.pdf3844 3845    return indicatePessimisticFixpoint();3846  }3847 3848  /// See AbstractAttribute::trackStatistics()3849  void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noalias) }3850};3851 3852struct AANoAliasCallSiteArgument final : AANoAliasImpl {3853  AANoAliasCallSiteArgument(const IRPosition &IRP, Attributor &A)3854      : AANoAliasImpl(IRP, A) {}3855 3856  /// Determine if the underlying value may alias with the call site argument3857  /// \p OtherArgNo of \p ICS (= the underlying call site).3858  bool mayAliasWithArgument(Attributor &A, AAResults *&AAR,3859                            const AAMemoryBehavior &MemBehaviorAA,3860                            const CallBase &CB, unsigned OtherArgNo) {3861    // We do not need to worry about aliasing with the underlying IRP.3862    if (this->getCalleeArgNo() == (int)OtherArgNo)3863      return false;3864 3865    // If it is not a pointer or pointer vector we do not alias.3866    const Value *ArgOp = CB.getArgOperand(OtherArgNo);3867    if (!ArgOp->getType()->isPtrOrPtrVectorTy())3868      return false;3869 3870    auto *CBArgMemBehaviorAA = A.getAAFor<AAMemoryBehavior>(3871        *this, IRPosition::callsite_argument(CB, OtherArgNo), DepClassTy::NONE);3872 3873    // If the argument is readnone, there is no read-write aliasing.3874    if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadNone()) {3875      A.recordDependence(*CBArgMemBehaviorAA, *this, DepClassTy::OPTIONAL);3876      return false;3877    }3878 3879    // If the argument is readonly and the underlying value is readonly, there3880    // is no read-write aliasing.3881    bool IsReadOnly = MemBehaviorAA.isAssumedReadOnly();3882    if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadOnly() &&3883        IsReadOnly) {3884      A.recordDependence(MemBehaviorAA, *this, DepClassTy::OPTIONAL);3885      A.recordDependence(*CBArgMemBehaviorAA, *this, DepClassTy::OPTIONAL);3886      return false;3887    }3888 3889    // We have to utilize actual alias analysis queries so we need the object.3890    if (!AAR)3891      AAR = A.getInfoCache().getAnalysisResultForFunction<AAManager>(3892          *getAnchorScope());3893 3894    // Try to rule it out at the call site.3895    bool IsAliasing = !AAR || !AAR->isNoAlias(&getAssociatedValue(), ArgOp);3896    LLVM_DEBUG(dbgs() << "[NoAliasCSArg] Check alias between "3897                         "callsite arguments: "3898                      << getAssociatedValue() << " " << *ArgOp << " => "3899                      << (IsAliasing ? "" : "no-") << "alias \n");3900 3901    return IsAliasing;3902  }3903 3904  bool isKnownNoAliasDueToNoAliasPreservation(3905      Attributor &A, AAResults *&AAR, const AAMemoryBehavior &MemBehaviorAA) {3906    // We can deduce "noalias" if the following conditions hold.3907    // (i)   Associated value is assumed to be noalias in the definition.3908    // (ii)  Associated value is assumed to be no-capture in all the uses3909    //       possibly executed before this callsite.3910    // (iii) There is no other pointer argument which could alias with the3911    //       value.3912 3913    const IRPosition &VIRP = IRPosition::value(getAssociatedValue());3914    const Function *ScopeFn = VIRP.getAnchorScope();3915    // Check whether the value is captured in the scope using AANoCapture.3916    // Look at CFG and check only uses possibly executed before this3917    // callsite.3918    auto UsePred = [&](const Use &U, bool &Follow) -> bool {3919      Instruction *UserI = cast<Instruction>(U.getUser());3920 3921      // If UserI is the curr instruction and there is a single potential use of3922      // the value in UserI we allow the use.3923      // TODO: We should inspect the operands and allow those that cannot alias3924      //       with the value.3925      if (UserI == getCtxI() && UserI->getNumOperands() == 1)3926        return true;3927 3928      if (ScopeFn) {3929        if (auto *CB = dyn_cast<CallBase>(UserI)) {3930          if (CB->isArgOperand(&U)) {3931 3932            unsigned ArgNo = CB->getArgOperandNo(&U);3933 3934            bool IsKnownNoCapture;3935            if (AA::hasAssumedIRAttr<Attribute::Captures>(3936                    A, this, IRPosition::callsite_argument(*CB, ArgNo),3937                    DepClassTy::OPTIONAL, IsKnownNoCapture))3938              return true;3939          }3940        }3941 3942        if (!AA::isPotentiallyReachable(3943                A, *UserI, *getCtxI(), *this, /* ExclusionSet */ nullptr,3944                [ScopeFn](const Function &Fn) { return &Fn != ScopeFn; }))3945          return true;3946      }3947 3948      // TODO: We should track the capturing uses in AANoCapture but the problem3949      //       is CGSCC runs. For those we would need to "allow" AANoCapture for3950      //       a value in the module slice.3951      // TODO(captures): Make this more precise.3952      UseCaptureInfo CI = DetermineUseCaptureKind(U, /*Base=*/nullptr);3953      if (capturesNothing(CI))3954        return true;3955      if (CI.isPassthrough()) {3956        Follow = true;3957        return true;3958      }3959      LLVM_DEBUG(dbgs() << "[AANoAliasCSArg] Unknown user: " << *UserI << "\n");3960      return false;3961    };3962 3963    bool IsKnownNoCapture;3964    const AANoCapture *NoCaptureAA = nullptr;3965    bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(3966        A, this, VIRP, DepClassTy::NONE, IsKnownNoCapture, false, &NoCaptureAA);3967    if (!IsAssumedNoCapture &&3968        (!NoCaptureAA || !NoCaptureAA->isAssumedNoCaptureMaybeReturned())) {3969      if (!A.checkForAllUses(UsePred, *this, getAssociatedValue())) {3970        LLVM_DEBUG(3971            dbgs() << "[AANoAliasCSArg] " << getAssociatedValue()3972                   << " cannot be noalias as it is potentially captured\n");3973        return false;3974      }3975    }3976    if (NoCaptureAA)3977      A.recordDependence(*NoCaptureAA, *this, DepClassTy::OPTIONAL);3978 3979    // Check there is no other pointer argument which could alias with the3980    // value passed at this call site.3981    // TODO: AbstractCallSite3982    const auto &CB = cast<CallBase>(getAnchorValue());3983    for (unsigned OtherArgNo = 0; OtherArgNo < CB.arg_size(); OtherArgNo++)3984      if (mayAliasWithArgument(A, AAR, MemBehaviorAA, CB, OtherArgNo))3985        return false;3986 3987    return true;3988  }3989 3990  /// See AbstractAttribute::updateImpl(...).3991  ChangeStatus updateImpl(Attributor &A) override {3992    // If the argument is readnone we are done as there are no accesses via the3993    // argument.3994    auto *MemBehaviorAA =3995        A.getAAFor<AAMemoryBehavior>(*this, getIRPosition(), DepClassTy::NONE);3996    if (MemBehaviorAA && MemBehaviorAA->isAssumedReadNone()) {3997      A.recordDependence(*MemBehaviorAA, *this, DepClassTy::OPTIONAL);3998      return ChangeStatus::UNCHANGED;3999    }4000 4001    bool IsKnownNoAlias;4002    const IRPosition &VIRP = IRPosition::value(getAssociatedValue());4003    if (!AA::hasAssumedIRAttr<Attribute::NoAlias>(4004            A, this, VIRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {4005      LLVM_DEBUG(dbgs() << "[AANoAlias] " << getAssociatedValue()4006                        << " is not no-alias at the definition\n");4007      return indicatePessimisticFixpoint();4008    }4009 4010    AAResults *AAR = nullptr;4011    if (MemBehaviorAA &&4012        isKnownNoAliasDueToNoAliasPreservation(A, AAR, *MemBehaviorAA)) {4013      LLVM_DEBUG(4014          dbgs() << "[AANoAlias] No-Alias deduced via no-alias preservation\n");4015      return ChangeStatus::UNCHANGED;4016    }4017 4018    return indicatePessimisticFixpoint();4019  }4020 4021  /// See AbstractAttribute::trackStatistics()4022  void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(noalias) }4023};4024 4025/// NoAlias attribute for function return value.4026struct AANoAliasReturned final : AANoAliasImpl {4027  AANoAliasReturned(const IRPosition &IRP, Attributor &A)4028      : AANoAliasImpl(IRP, A) {}4029 4030  /// See AbstractAttribute::updateImpl(...).4031  ChangeStatus updateImpl(Attributor &A) override {4032 4033    auto CheckReturnValue = [&](Value &RV) -> bool {4034      if (Constant *C = dyn_cast<Constant>(&RV))4035        if (C->isNullValue() || isa<UndefValue>(C))4036          return true;4037 4038      /// For now, we can only deduce noalias if we have call sites.4039      /// FIXME: add more support.4040      if (!isa<CallBase>(&RV))4041        return false;4042 4043      const IRPosition &RVPos = IRPosition::value(RV);4044      bool IsKnownNoAlias;4045      if (!AA::hasAssumedIRAttr<Attribute::NoAlias>(4046              A, this, RVPos, DepClassTy::REQUIRED, IsKnownNoAlias))4047        return false;4048 4049      bool IsKnownNoCapture;4050      const AANoCapture *NoCaptureAA = nullptr;4051      bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(4052          A, this, RVPos, DepClassTy::REQUIRED, IsKnownNoCapture, false,4053          &NoCaptureAA);4054      return IsAssumedNoCapture ||4055             (NoCaptureAA && NoCaptureAA->isAssumedNoCaptureMaybeReturned());4056    };4057 4058    if (!A.checkForAllReturnedValues(CheckReturnValue, *this))4059      return indicatePessimisticFixpoint();4060 4061    return ChangeStatus::UNCHANGED;4062  }4063 4064  /// See AbstractAttribute::trackStatistics()4065  void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noalias) }4066};4067 4068/// NoAlias attribute deduction for a call site return value.4069struct AANoAliasCallSiteReturned final4070    : AACalleeToCallSite<AANoAlias, AANoAliasImpl> {4071  AANoAliasCallSiteReturned(const IRPosition &IRP, Attributor &A)4072      : AACalleeToCallSite<AANoAlias, AANoAliasImpl>(IRP, A) {}4073 4074  /// See AbstractAttribute::trackStatistics()4075  void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noalias); }4076};4077} // namespace4078 4079/// -------------------AAIsDead Function Attribute-----------------------4080 4081namespace {4082struct AAIsDeadValueImpl : public AAIsDead {4083  AAIsDeadValueImpl(const IRPosition &IRP, Attributor &A) : AAIsDead(IRP, A) {}4084 4085  /// See AAIsDead::isAssumedDead().4086  bool isAssumedDead() const override { return isAssumed(IS_DEAD); }4087 4088  /// See AAIsDead::isKnownDead().4089  bool isKnownDead() const override { return isKnown(IS_DEAD); }4090 4091  /// See AAIsDead::isAssumedDead(BasicBlock *).4092  bool isAssumedDead(const BasicBlock *BB) const override { return false; }4093 4094  /// See AAIsDead::isKnownDead(BasicBlock *).4095  bool isKnownDead(const BasicBlock *BB) const override { return false; }4096 4097  /// See AAIsDead::isAssumedDead(Instruction *I).4098  bool isAssumedDead(const Instruction *I) const override {4099    return I == getCtxI() && isAssumedDead();4100  }4101 4102  /// See AAIsDead::isKnownDead(Instruction *I).4103  bool isKnownDead(const Instruction *I) const override {4104    return isAssumedDead(I) && isKnownDead();4105  }4106 4107  /// See AbstractAttribute::getAsStr().4108  const std::string getAsStr(Attributor *A) const override {4109    return isAssumedDead() ? "assumed-dead" : "assumed-live";4110  }4111 4112  /// Check if all uses are assumed dead.4113  bool areAllUsesAssumedDead(Attributor &A, Value &V) {4114    // Callers might not check the type, void has no uses.4115    if (V.getType()->isVoidTy() || V.use_empty())4116      return true;4117 4118    // If we replace a value with a constant there are no uses left afterwards.4119    if (!isa<Constant>(V)) {4120      if (auto *I = dyn_cast<Instruction>(&V))4121        if (!A.isRunOn(*I->getFunction()))4122          return false;4123      bool UsedAssumedInformation = false;4124      std::optional<Constant *> C =4125          A.getAssumedConstant(V, *this, UsedAssumedInformation);4126      if (!C || *C)4127        return true;4128    }4129 4130    auto UsePred = [&](const Use &U, bool &Follow) { return false; };4131    // Explicitly set the dependence class to required because we want a long4132    // chain of N dependent instructions to be considered live as soon as one is4133    // without going through N update cycles. This is not required for4134    // correctness.4135    return A.checkForAllUses(UsePred, *this, V, /* CheckBBLivenessOnly */ false,4136                             DepClassTy::REQUIRED,4137                             /* IgnoreDroppableUses */ false);4138  }4139 4140  /// Determine if \p I is assumed to be side-effect free.4141  bool isAssumedSideEffectFree(Attributor &A, Instruction *I) {4142    if (!I || wouldInstructionBeTriviallyDead(I))4143      return true;4144 4145    auto *CB = dyn_cast<CallBase>(I);4146    if (!CB || isa<IntrinsicInst>(CB))4147      return false;4148 4149    const IRPosition &CallIRP = IRPosition::callsite_function(*CB);4150 4151    bool IsKnownNoUnwind;4152    if (!AA::hasAssumedIRAttr<Attribute::NoUnwind>(4153            A, this, CallIRP, DepClassTy::OPTIONAL, IsKnownNoUnwind))4154      return false;4155 4156    bool IsKnown;4157    return AA::isAssumedReadOnly(A, CallIRP, *this, IsKnown);4158  }4159};4160 4161struct AAIsDeadFloating : public AAIsDeadValueImpl {4162  AAIsDeadFloating(const IRPosition &IRP, Attributor &A)4163      : AAIsDeadValueImpl(IRP, A) {}4164 4165  /// See AbstractAttribute::initialize(...).4166  void initialize(Attributor &A) override {4167    AAIsDeadValueImpl::initialize(A);4168 4169    if (isa<UndefValue>(getAssociatedValue())) {4170      indicatePessimisticFixpoint();4171      return;4172    }4173 4174    Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());4175    if (!isAssumedSideEffectFree(A, I)) {4176      if (!isa_and_nonnull<StoreInst>(I) && !isa_and_nonnull<FenceInst>(I))4177        indicatePessimisticFixpoint();4178      else4179        removeAssumedBits(HAS_NO_EFFECT);4180    }4181  }4182 4183  bool isDeadFence(Attributor &A, FenceInst &FI) {4184    const auto *ExecDomainAA = A.lookupAAFor<AAExecutionDomain>(4185        IRPosition::function(*FI.getFunction()), *this, DepClassTy::NONE);4186    if (!ExecDomainAA || !ExecDomainAA->isNoOpFence(FI))4187      return false;4188    A.recordDependence(*ExecDomainAA, *this, DepClassTy::OPTIONAL);4189    return true;4190  }4191 4192  bool isDeadStore(Attributor &A, StoreInst &SI,4193                   SmallSetVector<Instruction *, 8> *AssumeOnlyInst = nullptr) {4194    // Lang ref now states volatile store is not UB/dead, let's skip them.4195    if (SI.isVolatile())4196      return false;4197 4198    // If we are collecting assumes to be deleted we are in the manifest stage.4199    // It's problematic to collect the potential copies again now so we use the4200    // cached ones.4201    bool UsedAssumedInformation = false;4202    if (!AssumeOnlyInst) {4203      PotentialCopies.clear();4204      if (!AA::getPotentialCopiesOfStoredValue(A, SI, PotentialCopies, *this,4205                                               UsedAssumedInformation)) {4206        LLVM_DEBUG(4207            dbgs()4208            << "[AAIsDead] Could not determine potential copies of store!\n");4209        return false;4210      }4211    }4212    LLVM_DEBUG(dbgs() << "[AAIsDead] Store has " << PotentialCopies.size()4213                      << " potential copies.\n");4214 4215    InformationCache &InfoCache = A.getInfoCache();4216    return llvm::all_of(PotentialCopies, [&](Value *V) {4217      if (A.isAssumedDead(IRPosition::value(*V), this, nullptr,4218                          UsedAssumedInformation))4219        return true;4220      if (auto *LI = dyn_cast<LoadInst>(V)) {4221        if (llvm::all_of(LI->uses(), [&](const Use &U) {4222              auto &UserI = cast<Instruction>(*U.getUser());4223              if (InfoCache.isOnlyUsedByAssume(UserI)) {4224                if (AssumeOnlyInst)4225                  AssumeOnlyInst->insert(&UserI);4226                return true;4227              }4228              return A.isAssumedDead(U, this, nullptr, UsedAssumedInformation);4229            })) {4230          return true;4231        }4232      }4233      LLVM_DEBUG(dbgs() << "[AAIsDead] Potential copy " << *V4234                        << " is assumed live!\n");4235      return false;4236    });4237  }4238 4239  /// See AbstractAttribute::getAsStr().4240  const std::string getAsStr(Attributor *A) const override {4241    Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());4242    if (isa_and_nonnull<StoreInst>(I))4243      if (isValidState())4244        return "assumed-dead-store";4245    if (isa_and_nonnull<FenceInst>(I))4246      if (isValidState())4247        return "assumed-dead-fence";4248    return AAIsDeadValueImpl::getAsStr(A);4249  }4250 4251  /// See AbstractAttribute::updateImpl(...).4252  ChangeStatus updateImpl(Attributor &A) override {4253    Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());4254    if (auto *SI = dyn_cast_or_null<StoreInst>(I)) {4255      if (!isDeadStore(A, *SI))4256        return indicatePessimisticFixpoint();4257    } else if (auto *FI = dyn_cast_or_null<FenceInst>(I)) {4258      if (!isDeadFence(A, *FI))4259        return indicatePessimisticFixpoint();4260    } else {4261      if (!isAssumedSideEffectFree(A, I))4262        return indicatePessimisticFixpoint();4263      if (!areAllUsesAssumedDead(A, getAssociatedValue()))4264        return indicatePessimisticFixpoint();4265    }4266    return ChangeStatus::UNCHANGED;4267  }4268 4269  bool isRemovableStore() const override {4270    return isAssumed(IS_REMOVABLE) && isa<StoreInst>(&getAssociatedValue());4271  }4272 4273  /// See AbstractAttribute::manifest(...).4274  ChangeStatus manifest(Attributor &A) override {4275    Value &V = getAssociatedValue();4276    if (auto *I = dyn_cast<Instruction>(&V)) {4277      // If we get here we basically know the users are all dead. We check if4278      // isAssumedSideEffectFree returns true here again because it might not be4279      // the case and only the users are dead but the instruction (=call) is4280      // still needed.4281      if (auto *SI = dyn_cast<StoreInst>(I)) {4282        SmallSetVector<Instruction *, 8> AssumeOnlyInst;4283        bool IsDead = isDeadStore(A, *SI, &AssumeOnlyInst);4284        (void)IsDead;4285        assert(IsDead && "Store was assumed to be dead!");4286        A.deleteAfterManifest(*I);4287        for (size_t i = 0; i < AssumeOnlyInst.size(); ++i) {4288          Instruction *AOI = AssumeOnlyInst[i];4289          for (auto *Usr : AOI->users())4290            AssumeOnlyInst.insert(cast<Instruction>(Usr));4291          A.deleteAfterManifest(*AOI);4292        }4293        return ChangeStatus::CHANGED;4294      }4295      if (auto *FI = dyn_cast<FenceInst>(I)) {4296        assert(isDeadFence(A, *FI));4297        A.deleteAfterManifest(*FI);4298        return ChangeStatus::CHANGED;4299      }4300      if (isAssumedSideEffectFree(A, I) && !isa<InvokeInst>(I)) {4301        A.deleteAfterManifest(*I);4302        return ChangeStatus::CHANGED;4303      }4304    }4305    return ChangeStatus::UNCHANGED;4306  }4307 4308  /// See AbstractAttribute::trackStatistics()4309  void trackStatistics() const override {4310    STATS_DECLTRACK_FLOATING_ATTR(IsDead)4311  }4312 4313private:4314  // The potential copies of a dead store, used for deletion during manifest.4315  SmallSetVector<Value *, 4> PotentialCopies;4316};4317 4318struct AAIsDeadArgument : public AAIsDeadFloating {4319  AAIsDeadArgument(const IRPosition &IRP, Attributor &A)4320      : AAIsDeadFloating(IRP, A) {}4321 4322  /// See AbstractAttribute::manifest(...).4323  ChangeStatus manifest(Attributor &A) override {4324    Argument &Arg = *getAssociatedArgument();4325    if (A.isValidFunctionSignatureRewrite(Arg, /* ReplacementTypes */ {}))4326      if (A.registerFunctionSignatureRewrite(4327              Arg, /* ReplacementTypes */ {},4328              Attributor::ArgumentReplacementInfo::CalleeRepairCBTy{},4329              Attributor::ArgumentReplacementInfo::ACSRepairCBTy{})) {4330        return ChangeStatus::CHANGED;4331      }4332    return ChangeStatus::UNCHANGED;4333  }4334 4335  /// See AbstractAttribute::trackStatistics()4336  void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(IsDead) }4337};4338 4339struct AAIsDeadCallSiteArgument : public AAIsDeadValueImpl {4340  AAIsDeadCallSiteArgument(const IRPosition &IRP, Attributor &A)4341      : AAIsDeadValueImpl(IRP, A) {}4342 4343  /// See AbstractAttribute::initialize(...).4344  void initialize(Attributor &A) override {4345    AAIsDeadValueImpl::initialize(A);4346    if (isa<UndefValue>(getAssociatedValue()))4347      indicatePessimisticFixpoint();4348  }4349 4350  /// See AbstractAttribute::updateImpl(...).4351  ChangeStatus updateImpl(Attributor &A) override {4352    // TODO: Once we have call site specific value information we can provide4353    //       call site specific liveness information and then it makes4354    //       sense to specialize attributes for call sites arguments instead of4355    //       redirecting requests to the callee argument.4356    Argument *Arg = getAssociatedArgument();4357    if (!Arg)4358      return indicatePessimisticFixpoint();4359    const IRPosition &ArgPos = IRPosition::argument(*Arg);4360    auto *ArgAA = A.getAAFor<AAIsDead>(*this, ArgPos, DepClassTy::REQUIRED);4361    if (!ArgAA)4362      return indicatePessimisticFixpoint();4363    return clampStateAndIndicateChange(getState(), ArgAA->getState());4364  }4365 4366  /// See AbstractAttribute::manifest(...).4367  ChangeStatus manifest(Attributor &A) override {4368    CallBase &CB = cast<CallBase>(getAnchorValue());4369    Use &U = CB.getArgOperandUse(getCallSiteArgNo());4370    assert(!isa<UndefValue>(U.get()) &&4371           "Expected undef values to be filtered out!");4372    UndefValue &UV = *UndefValue::get(U->getType());4373    if (A.changeUseAfterManifest(U, UV))4374      return ChangeStatus::CHANGED;4375    return ChangeStatus::UNCHANGED;4376  }4377 4378  /// See AbstractAttribute::trackStatistics()4379  void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(IsDead) }4380};4381 4382struct AAIsDeadCallSiteReturned : public AAIsDeadFloating {4383  AAIsDeadCallSiteReturned(const IRPosition &IRP, Attributor &A)4384      : AAIsDeadFloating(IRP, A) {}4385 4386  /// See AAIsDead::isAssumedDead().4387  bool isAssumedDead() const override {4388    return AAIsDeadFloating::isAssumedDead() && IsAssumedSideEffectFree;4389  }4390 4391  /// See AbstractAttribute::initialize(...).4392  void initialize(Attributor &A) override {4393    AAIsDeadFloating::initialize(A);4394    if (isa<UndefValue>(getAssociatedValue())) {4395      indicatePessimisticFixpoint();4396      return;4397    }4398 4399    // We track this separately as a secondary state.4400    IsAssumedSideEffectFree = isAssumedSideEffectFree(A, getCtxI());4401  }4402 4403  /// See AbstractAttribute::updateImpl(...).4404  ChangeStatus updateImpl(Attributor &A) override {4405    ChangeStatus Changed = ChangeStatus::UNCHANGED;4406    if (IsAssumedSideEffectFree && !isAssumedSideEffectFree(A, getCtxI())) {4407      IsAssumedSideEffectFree = false;4408      Changed = ChangeStatus::CHANGED;4409    }4410    if (!areAllUsesAssumedDead(A, getAssociatedValue()))4411      return indicatePessimisticFixpoint();4412    return Changed;4413  }4414 4415  /// See AbstractAttribute::trackStatistics()4416  void trackStatistics() const override {4417    if (IsAssumedSideEffectFree)4418      STATS_DECLTRACK_CSRET_ATTR(IsDead)4419    else4420      STATS_DECLTRACK_CSRET_ATTR(UnusedResult)4421  }4422 4423  /// See AbstractAttribute::getAsStr().4424  const std::string getAsStr(Attributor *A) const override {4425    return isAssumedDead()4426               ? "assumed-dead"4427               : (getAssumed() ? "assumed-dead-users" : "assumed-live");4428  }4429 4430private:4431  bool IsAssumedSideEffectFree = true;4432};4433 4434struct AAIsDeadReturned : public AAIsDeadValueImpl {4435  AAIsDeadReturned(const IRPosition &IRP, Attributor &A)4436      : AAIsDeadValueImpl(IRP, A) {}4437 4438  /// See AbstractAttribute::updateImpl(...).4439  ChangeStatus updateImpl(Attributor &A) override {4440 4441    bool UsedAssumedInformation = false;4442    A.checkForAllInstructions([](Instruction &) { return true; }, *this,4443                              {Instruction::Ret}, UsedAssumedInformation);4444 4445    auto PredForCallSite = [&](AbstractCallSite ACS) {4446      if (ACS.isCallbackCall() || !ACS.getInstruction())4447        return false;4448      return areAllUsesAssumedDead(A, *ACS.getInstruction());4449    };4450 4451    if (!A.checkForAllCallSites(PredForCallSite, *this, true,4452                                UsedAssumedInformation))4453      return indicatePessimisticFixpoint();4454 4455    return ChangeStatus::UNCHANGED;4456  }4457 4458  /// See AbstractAttribute::manifest(...).4459  ChangeStatus manifest(Attributor &A) override {4460    // TODO: Rewrite the signature to return void?4461    bool AnyChange = false;4462    UndefValue &UV = *UndefValue::get(getAssociatedFunction()->getReturnType());4463    auto RetInstPred = [&](Instruction &I) {4464      ReturnInst &RI = cast<ReturnInst>(I);4465      if (!isa<UndefValue>(RI.getReturnValue()))4466        AnyChange |= A.changeUseAfterManifest(RI.getOperandUse(0), UV);4467      return true;4468    };4469    bool UsedAssumedInformation = false;4470    A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret},4471                              UsedAssumedInformation);4472    return AnyChange ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;4473  }4474 4475  /// See AbstractAttribute::trackStatistics()4476  void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(IsDead) }4477};4478 4479struct AAIsDeadFunction : public AAIsDead {4480  AAIsDeadFunction(const IRPosition &IRP, Attributor &A) : AAIsDead(IRP, A) {}4481 4482  /// See AbstractAttribute::initialize(...).4483  void initialize(Attributor &A) override {4484    Function *F = getAnchorScope();4485    assert(F && "Did expect an anchor function");4486    if (!isAssumedDeadInternalFunction(A)) {4487      ToBeExploredFrom.insert(&F->getEntryBlock().front());4488      assumeLive(A, F->getEntryBlock());4489    }4490  }4491 4492  bool isAssumedDeadInternalFunction(Attributor &A) {4493    if (!getAnchorScope()->hasLocalLinkage())4494      return false;4495    bool UsedAssumedInformation = false;4496    return A.checkForAllCallSites([](AbstractCallSite) { return false; }, *this,4497                                  true, UsedAssumedInformation);4498  }4499 4500  /// See AbstractAttribute::getAsStr().4501  const std::string getAsStr(Attributor *A) const override {4502    return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) + "/" +4503           std::to_string(getAnchorScope()->size()) + "][#TBEP " +4504           std::to_string(ToBeExploredFrom.size()) + "][#KDE " +4505           std::to_string(KnownDeadEnds.size()) + "]";4506  }4507 4508  /// See AbstractAttribute::manifest(...).4509  ChangeStatus manifest(Attributor &A) override {4510    assert(getState().isValidState() &&4511           "Attempted to manifest an invalid state!");4512 4513    ChangeStatus HasChanged = ChangeStatus::UNCHANGED;4514    Function &F = *getAnchorScope();4515 4516    if (AssumedLiveBlocks.empty()) {4517      A.deleteAfterManifest(F);4518      return ChangeStatus::CHANGED;4519    }4520 4521    // Flag to determine if we can change an invoke to a call assuming the4522    // callee is nounwind. This is not possible if the personality of the4523    // function allows to catch asynchronous exceptions.4524    bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);4525 4526    KnownDeadEnds.set_union(ToBeExploredFrom);4527    for (const Instruction *DeadEndI : KnownDeadEnds) {4528      auto *CB = dyn_cast<CallBase>(DeadEndI);4529      if (!CB)4530        continue;4531      bool IsKnownNoReturn;4532      bool MayReturn = !AA::hasAssumedIRAttr<Attribute::NoReturn>(4533          A, this, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL,4534          IsKnownNoReturn);4535      if (MayReturn && (!Invoke2CallAllowed || !isa<InvokeInst>(CB)))4536        continue;4537 4538      if (auto *II = dyn_cast<InvokeInst>(DeadEndI))4539        A.registerInvokeWithDeadSuccessor(const_cast<InvokeInst &>(*II));4540      else4541        A.changeToUnreachableAfterManifest(4542            const_cast<Instruction *>(DeadEndI->getNextNode()));4543      HasChanged = ChangeStatus::CHANGED;4544    }4545 4546    STATS_DECL(AAIsDead, BasicBlock, "Number of dead basic blocks deleted.");4547    for (BasicBlock &BB : F)4548      if (!AssumedLiveBlocks.count(&BB)) {4549        A.deleteAfterManifest(BB);4550        ++BUILD_STAT_NAME(AAIsDead, BasicBlock);4551        HasChanged = ChangeStatus::CHANGED;4552      }4553 4554    return HasChanged;4555  }4556 4557  /// See AbstractAttribute::updateImpl(...).4558  ChangeStatus updateImpl(Attributor &A) override;4559 4560  bool isEdgeDead(const BasicBlock *From, const BasicBlock *To) const override {4561    assert(From->getParent() == getAnchorScope() &&4562           To->getParent() == getAnchorScope() &&4563           "Used AAIsDead of the wrong function");4564    return isValidState() && !AssumedLiveEdges.count(std::make_pair(From, To));4565  }4566 4567  /// See AbstractAttribute::trackStatistics()4568  void trackStatistics() const override {}4569 4570  /// Returns true if the function is assumed dead.4571  bool isAssumedDead() const override { return false; }4572 4573  /// See AAIsDead::isKnownDead().4574  bool isKnownDead() const override { return false; }4575 4576  /// See AAIsDead::isAssumedDead(BasicBlock *).4577  bool isAssumedDead(const BasicBlock *BB) const override {4578    assert(BB->getParent() == getAnchorScope() &&4579           "BB must be in the same anchor scope function.");4580 4581    if (!getAssumed())4582      return false;4583    return !AssumedLiveBlocks.count(BB);4584  }4585 4586  /// See AAIsDead::isKnownDead(BasicBlock *).4587  bool isKnownDead(const BasicBlock *BB) const override {4588    return getKnown() && isAssumedDead(BB);4589  }4590 4591  /// See AAIsDead::isAssumed(Instruction *I).4592  bool isAssumedDead(const Instruction *I) const override {4593    assert(I->getParent()->getParent() == getAnchorScope() &&4594           "Instruction must be in the same anchor scope function.");4595 4596    if (!getAssumed())4597      return false;4598 4599    // If it is not in AssumedLiveBlocks then it for sure dead.4600    // Otherwise, it can still be after noreturn call in a live block.4601    if (!AssumedLiveBlocks.count(I->getParent()))4602      return true;4603 4604    // If it is not after a liveness barrier it is live.4605    const Instruction *PrevI = I->getPrevNode();4606    while (PrevI) {4607      if (KnownDeadEnds.count(PrevI) || ToBeExploredFrom.count(PrevI))4608        return true;4609      PrevI = PrevI->getPrevNode();4610    }4611    return false;4612  }4613 4614  /// See AAIsDead::isKnownDead(Instruction *I).4615  bool isKnownDead(const Instruction *I) const override {4616    return getKnown() && isAssumedDead(I);4617  }4618 4619  /// Assume \p BB is (partially) live now and indicate to the Attributor \p A4620  /// that internal function called from \p BB should now be looked at.4621  bool assumeLive(Attributor &A, const BasicBlock &BB) {4622    if (!AssumedLiveBlocks.insert(&BB).second)4623      return false;4624 4625    // We assume that all of BB is (probably) live now and if there are calls to4626    // internal functions we will assume that those are now live as well. This4627    // is a performance optimization for blocks with calls to a lot of internal4628    // functions. It can however cause dead functions to be treated as live.4629    for (const Instruction &I : BB)4630      if (const auto *CB = dyn_cast<CallBase>(&I))4631        if (auto *F = dyn_cast_if_present<Function>(CB->getCalledOperand()))4632          if (F->hasLocalLinkage())4633            A.markLiveInternalFunction(*F);4634    return true;4635  }4636 4637  /// Collection of instructions that need to be explored again, e.g., we4638  /// did assume they do not transfer control to (one of their) successors.4639  SmallSetVector<const Instruction *, 8> ToBeExploredFrom;4640 4641  /// Collection of instructions that are known to not transfer control.4642  SmallSetVector<const Instruction *, 8> KnownDeadEnds;4643 4644  /// Collection of all assumed live edges4645  DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> AssumedLiveEdges;4646 4647  /// Collection of all assumed live BasicBlocks.4648  DenseSet<const BasicBlock *> AssumedLiveBlocks;4649};4650 4651static bool4652identifyAliveSuccessors(Attributor &A, const CallBase &CB,4653                        AbstractAttribute &AA,4654                        SmallVectorImpl<const Instruction *> &AliveSuccessors) {4655  const IRPosition &IPos = IRPosition::callsite_function(CB);4656 4657  bool IsKnownNoReturn;4658  if (AA::hasAssumedIRAttr<Attribute::NoReturn>(4659          A, &AA, IPos, DepClassTy::OPTIONAL, IsKnownNoReturn))4660    return !IsKnownNoReturn;4661  if (CB.isTerminator())4662    AliveSuccessors.push_back(&CB.getSuccessor(0)->front());4663  else4664    AliveSuccessors.push_back(CB.getNextNode());4665  return false;4666}4667 4668static bool4669identifyAliveSuccessors(Attributor &A, const InvokeInst &II,4670                        AbstractAttribute &AA,4671                        SmallVectorImpl<const Instruction *> &AliveSuccessors) {4672  bool UsedAssumedInformation =4673      identifyAliveSuccessors(A, cast<CallBase>(II), AA, AliveSuccessors);4674 4675  // First, determine if we can change an invoke to a call assuming the4676  // callee is nounwind. This is not possible if the personality of the4677  // function allows to catch asynchronous exceptions.4678  if (AAIsDeadFunction::mayCatchAsynchronousExceptions(*II.getFunction())) {4679    AliveSuccessors.push_back(&II.getUnwindDest()->front());4680  } else {4681    const IRPosition &IPos = IRPosition::callsite_function(II);4682 4683    bool IsKnownNoUnwind;4684    if (AA::hasAssumedIRAttr<Attribute::NoUnwind>(4685            A, &AA, IPos, DepClassTy::OPTIONAL, IsKnownNoUnwind)) {4686      UsedAssumedInformation |= !IsKnownNoUnwind;4687    } else {4688      AliveSuccessors.push_back(&II.getUnwindDest()->front());4689    }4690  }4691  return UsedAssumedInformation;4692}4693 4694static bool4695identifyAliveSuccessors(Attributor &A, const BranchInst &BI,4696                        AbstractAttribute &AA,4697                        SmallVectorImpl<const Instruction *> &AliveSuccessors) {4698  bool UsedAssumedInformation = false;4699  if (BI.getNumSuccessors() == 1) {4700    AliveSuccessors.push_back(&BI.getSuccessor(0)->front());4701  } else {4702    std::optional<Constant *> C =4703        A.getAssumedConstant(*BI.getCondition(), AA, UsedAssumedInformation);4704    if (!C || isa_and_nonnull<UndefValue>(*C)) {4705      // No value yet, assume both edges are dead.4706    } else if (isa_and_nonnull<ConstantInt>(*C)) {4707      const BasicBlock *SuccBB =4708          BI.getSuccessor(1 - cast<ConstantInt>(*C)->getValue().getZExtValue());4709      AliveSuccessors.push_back(&SuccBB->front());4710    } else {4711      AliveSuccessors.push_back(&BI.getSuccessor(0)->front());4712      AliveSuccessors.push_back(&BI.getSuccessor(1)->front());4713      UsedAssumedInformation = false;4714    }4715  }4716  return UsedAssumedInformation;4717}4718 4719static bool4720identifyAliveSuccessors(Attributor &A, const SwitchInst &SI,4721                        AbstractAttribute &AA,4722                        SmallVectorImpl<const Instruction *> &AliveSuccessors) {4723  bool UsedAssumedInformation = false;4724  SmallVector<AA::ValueAndContext> Values;4725  if (!A.getAssumedSimplifiedValues(IRPosition::value(*SI.getCondition()), &AA,4726                                    Values, AA::AnyScope,4727                                    UsedAssumedInformation)) {4728    // Something went wrong, assume all successors are live.4729    for (const BasicBlock *SuccBB : successors(SI.getParent()))4730      AliveSuccessors.push_back(&SuccBB->front());4731    return false;4732  }4733 4734  if (Values.empty() ||4735      (Values.size() == 1 &&4736       isa_and_nonnull<UndefValue>(Values.front().getValue()))) {4737    // No valid value yet, assume all edges are dead.4738    return UsedAssumedInformation;4739  }4740 4741  Type &Ty = *SI.getCondition()->getType();4742  SmallPtrSet<ConstantInt *, 8> Constants;4743  auto CheckForConstantInt = [&](Value *V) {4744    if (auto *CI = dyn_cast_if_present<ConstantInt>(AA::getWithType(*V, Ty))) {4745      Constants.insert(CI);4746      return true;4747    }4748    return false;4749  };4750 4751  if (!all_of(Values, [&](AA::ValueAndContext &VAC) {4752        return CheckForConstantInt(VAC.getValue());4753      })) {4754    for (const BasicBlock *SuccBB : successors(SI.getParent()))4755      AliveSuccessors.push_back(&SuccBB->front());4756    return UsedAssumedInformation;4757  }4758 4759  unsigned MatchedCases = 0;4760  for (const auto &CaseIt : SI.cases()) {4761    if (Constants.count(CaseIt.getCaseValue())) {4762      ++MatchedCases;4763      AliveSuccessors.push_back(&CaseIt.getCaseSuccessor()->front());4764    }4765  }4766 4767  // If all potential values have been matched, we will not visit the default4768  // case.4769  if (MatchedCases < Constants.size())4770    AliveSuccessors.push_back(&SI.getDefaultDest()->front());4771  return UsedAssumedInformation;4772}4773 4774ChangeStatus AAIsDeadFunction::updateImpl(Attributor &A) {4775  ChangeStatus Change = ChangeStatus::UNCHANGED;4776 4777  if (AssumedLiveBlocks.empty()) {4778    if (isAssumedDeadInternalFunction(A))4779      return ChangeStatus::UNCHANGED;4780 4781    Function *F = getAnchorScope();4782    ToBeExploredFrom.insert(&F->getEntryBlock().front());4783    assumeLive(A, F->getEntryBlock());4784    Change = ChangeStatus::CHANGED;4785  }4786 4787  LLVM_DEBUG(dbgs() << "[AAIsDead] Live [" << AssumedLiveBlocks.size() << "/"4788                    << getAnchorScope()->size() << "] BBs and "4789                    << ToBeExploredFrom.size() << " exploration points and "4790                    << KnownDeadEnds.size() << " known dead ends\n");4791 4792  // Copy and clear the list of instructions we need to explore from. It is4793  // refilled with instructions the next update has to look at.4794  SmallVector<const Instruction *, 8> Worklist(ToBeExploredFrom.begin(),4795                                               ToBeExploredFrom.end());4796  decltype(ToBeExploredFrom) NewToBeExploredFrom;4797 4798  SmallVector<const Instruction *, 8> AliveSuccessors;4799  while (!Worklist.empty()) {4800    const Instruction *I = Worklist.pop_back_val();4801    LLVM_DEBUG(dbgs() << "[AAIsDead] Exploration inst: " << *I << "\n");4802 4803    // Fast forward for uninteresting instructions. We could look for UB here4804    // though.4805    while (!I->isTerminator() && !isa<CallBase>(I))4806      I = I->getNextNode();4807 4808    AliveSuccessors.clear();4809 4810    bool UsedAssumedInformation = false;4811    switch (I->getOpcode()) {4812    // TODO: look for (assumed) UB to backwards propagate "deadness".4813    default:4814      assert(I->isTerminator() &&4815             "Expected non-terminators to be handled already!");4816      for (const BasicBlock *SuccBB : successors(I->getParent()))4817        AliveSuccessors.push_back(&SuccBB->front());4818      break;4819    case Instruction::Call:4820      UsedAssumedInformation = identifyAliveSuccessors(A, cast<CallInst>(*I),4821                                                       *this, AliveSuccessors);4822      break;4823    case Instruction::Invoke:4824      UsedAssumedInformation = identifyAliveSuccessors(A, cast<InvokeInst>(*I),4825                                                       *this, AliveSuccessors);4826      break;4827    case Instruction::Br:4828      UsedAssumedInformation = identifyAliveSuccessors(A, cast<BranchInst>(*I),4829                                                       *this, AliveSuccessors);4830      break;4831    case Instruction::Switch:4832      UsedAssumedInformation = identifyAliveSuccessors(A, cast<SwitchInst>(*I),4833                                                       *this, AliveSuccessors);4834      break;4835    }4836 4837    if (UsedAssumedInformation) {4838      NewToBeExploredFrom.insert(I);4839    } else if (AliveSuccessors.empty() ||4840               (I->isTerminator() &&4841                AliveSuccessors.size() < I->getNumSuccessors())) {4842      if (KnownDeadEnds.insert(I))4843        Change = ChangeStatus::CHANGED;4844    }4845 4846    LLVM_DEBUG(dbgs() << "[AAIsDead] #AliveSuccessors: "4847                      << AliveSuccessors.size() << " UsedAssumedInformation: "4848                      << UsedAssumedInformation << "\n");4849 4850    for (const Instruction *AliveSuccessor : AliveSuccessors) {4851      if (!I->isTerminator()) {4852        assert(AliveSuccessors.size() == 1 &&4853               "Non-terminator expected to have a single successor!");4854        Worklist.push_back(AliveSuccessor);4855      } else {4856        // record the assumed live edge4857        auto Edge = std::make_pair(I->getParent(), AliveSuccessor->getParent());4858        if (AssumedLiveEdges.insert(Edge).second)4859          Change = ChangeStatus::CHANGED;4860        if (assumeLive(A, *AliveSuccessor->getParent()))4861          Worklist.push_back(AliveSuccessor);4862      }4863    }4864  }4865 4866  // Check if the content of ToBeExploredFrom changed, ignore the order.4867  if (NewToBeExploredFrom.size() != ToBeExploredFrom.size() ||4868      llvm::any_of(NewToBeExploredFrom, [&](const Instruction *I) {4869        return !ToBeExploredFrom.count(I);4870      })) {4871    Change = ChangeStatus::CHANGED;4872    ToBeExploredFrom = std::move(NewToBeExploredFrom);4873  }4874 4875  // If we know everything is live there is no need to query for liveness.4876  // Instead, indicating a pessimistic fixpoint will cause the state to be4877  // "invalid" and all queries to be answered conservatively without lookups.4878  // To be in this state we have to (1) finished the exploration and (3) not4879  // discovered any non-trivial dead end and (2) not ruled unreachable code4880  // dead.4881  if (ToBeExploredFrom.empty() &&4882      getAnchorScope()->size() == AssumedLiveBlocks.size() &&4883      llvm::all_of(KnownDeadEnds, [](const Instruction *DeadEndI) {4884        return DeadEndI->isTerminator() && DeadEndI->getNumSuccessors() == 0;4885      }))4886    return indicatePessimisticFixpoint();4887  return Change;4888}4889 4890/// Liveness information for a call sites.4891struct AAIsDeadCallSite final : AAIsDeadFunction {4892  AAIsDeadCallSite(const IRPosition &IRP, Attributor &A)4893      : AAIsDeadFunction(IRP, A) {}4894 4895  /// See AbstractAttribute::initialize(...).4896  void initialize(Attributor &A) override {4897    // TODO: Once we have call site specific value information we can provide4898    //       call site specific liveness information and then it makes4899    //       sense to specialize attributes for call sites instead of4900    //       redirecting requests to the callee.4901    llvm_unreachable("Abstract attributes for liveness are not "4902                     "supported for call sites yet!");4903  }4904 4905  /// See AbstractAttribute::updateImpl(...).4906  ChangeStatus updateImpl(Attributor &A) override {4907    return indicatePessimisticFixpoint();4908  }4909 4910  /// See AbstractAttribute::trackStatistics()4911  void trackStatistics() const override {}4912};4913} // namespace4914 4915/// -------------------- Dereferenceable Argument Attribute --------------------4916 4917namespace {4918struct AADereferenceableImpl : AADereferenceable {4919  AADereferenceableImpl(const IRPosition &IRP, Attributor &A)4920      : AADereferenceable(IRP, A) {}4921  using StateType = DerefState;4922 4923  /// See AbstractAttribute::initialize(...).4924  void initialize(Attributor &A) override {4925    Value &V = *getAssociatedValue().stripPointerCasts();4926    SmallVector<Attribute, 4> Attrs;4927    A.getAttrs(getIRPosition(),4928               {Attribute::Dereferenceable, Attribute::DereferenceableOrNull},4929               Attrs, /* IgnoreSubsumingPositions */ false);4930    for (const Attribute &Attr : Attrs)4931      takeKnownDerefBytesMaximum(Attr.getValueAsInt());4932 4933    // Ensure we initialize the non-null AA (if necessary).4934    bool IsKnownNonNull;4935    AA::hasAssumedIRAttr<Attribute::NonNull>(4936        A, this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNonNull);4937 4938    bool CanBeNull, CanBeFreed;4939    takeKnownDerefBytesMaximum(V.getPointerDereferenceableBytes(4940        A.getDataLayout(), CanBeNull, CanBeFreed));4941 4942    if (Instruction *CtxI = getCtxI())4943      followUsesInMBEC(*this, A, getState(), *CtxI);4944  }4945 4946  /// See AbstractAttribute::getState()4947  /// {4948  StateType &getState() override { return *this; }4949  const StateType &getState() const override { return *this; }4950  /// }4951 4952  /// Helper function for collecting accessed bytes in must-be-executed-context4953  void addAccessedBytesForUse(Attributor &A, const Use *U, const Instruction *I,4954                              DerefState &State) {4955    const Value *UseV = U->get();4956    if (!UseV->getType()->isPointerTy())4957      return;4958 4959    std::optional<MemoryLocation> Loc = MemoryLocation::getOrNone(I);4960    if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() || I->isVolatile())4961      return;4962 4963    int64_t Offset;4964    const Value *Base = GetPointerBaseWithConstantOffset(4965        Loc->Ptr, Offset, A.getDataLayout(), /*AllowNonInbounds*/ true);4966    if (Base && Base == &getAssociatedValue())4967      State.addAccessedBytes(Offset, Loc->Size.getValue());4968  }4969 4970  /// See followUsesInMBEC4971  bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,4972                       AADereferenceable::StateType &State) {4973    bool IsNonNull = false;4974    bool TrackUse = false;4975    int64_t DerefBytes = getKnownNonNullAndDerefBytesForUse(4976        A, *this, getAssociatedValue(), U, I, IsNonNull, TrackUse);4977    LLVM_DEBUG(dbgs() << "[AADereferenceable] Deref bytes: " << DerefBytes4978                      << " for instruction " << *I << "\n");4979 4980    addAccessedBytesForUse(A, U, I, State);4981    State.takeKnownDerefBytesMaximum(DerefBytes);4982    return TrackUse;4983  }4984 4985  /// See AbstractAttribute::manifest(...).4986  ChangeStatus manifest(Attributor &A) override {4987    ChangeStatus Change = AADereferenceable::manifest(A);4988    bool IsKnownNonNull;4989    bool IsAssumedNonNull = AA::hasAssumedIRAttr<Attribute::NonNull>(4990        A, this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);4991    if (IsAssumedNonNull &&4992        A.hasAttr(getIRPosition(), Attribute::DereferenceableOrNull)) {4993      A.removeAttrs(getIRPosition(), {Attribute::DereferenceableOrNull});4994      return ChangeStatus::CHANGED;4995    }4996    return Change;4997  }4998 4999  void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,5000                            SmallVectorImpl<Attribute> &Attrs) const override {5001    // TODO: Add *_globally support5002    bool IsKnownNonNull;5003    bool IsAssumedNonNull = AA::hasAssumedIRAttr<Attribute::NonNull>(5004        A, this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);5005    if (IsAssumedNonNull)5006      Attrs.emplace_back(Attribute::getWithDereferenceableBytes(5007          Ctx, getAssumedDereferenceableBytes()));5008    else5009      Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(5010          Ctx, getAssumedDereferenceableBytes()));5011  }5012 5013  /// See AbstractAttribute::getAsStr().5014  const std::string getAsStr(Attributor *A) const override {5015    if (!getAssumedDereferenceableBytes())5016      return "unknown-dereferenceable";5017    bool IsKnownNonNull;5018    bool IsAssumedNonNull = false;5019    if (A)5020      IsAssumedNonNull = AA::hasAssumedIRAttr<Attribute::NonNull>(5021          *A, this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);5022    return std::string("dereferenceable") +5023           (IsAssumedNonNull ? "" : "_or_null") +5024           (isAssumedGlobal() ? "_globally" : "") + "<" +5025           std::to_string(getKnownDereferenceableBytes()) + "-" +5026           std::to_string(getAssumedDereferenceableBytes()) + ">" +5027           (!A ? " [non-null is unknown]" : "");5028  }5029};5030 5031/// Dereferenceable attribute for a floating value.5032struct AADereferenceableFloating : AADereferenceableImpl {5033  AADereferenceableFloating(const IRPosition &IRP, Attributor &A)5034      : AADereferenceableImpl(IRP, A) {}5035 5036  /// See AbstractAttribute::updateImpl(...).5037  ChangeStatus updateImpl(Attributor &A) override {5038    bool Stripped;5039    bool UsedAssumedInformation = false;5040    SmallVector<AA::ValueAndContext> Values;5041    if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,5042                                      AA::AnyScope, UsedAssumedInformation)) {5043      Values.push_back({getAssociatedValue(), getCtxI()});5044      Stripped = false;5045    } else {5046      Stripped = Values.size() != 1 ||5047                 Values.front().getValue() != &getAssociatedValue();5048    }5049 5050    const DataLayout &DL = A.getDataLayout();5051    DerefState T;5052 5053    auto VisitValueCB = [&](const Value &V) -> bool {5054      unsigned IdxWidth =5055          DL.getIndexSizeInBits(V.getType()->getPointerAddressSpace());5056      APInt Offset(IdxWidth, 0);5057      const Value *Base = stripAndAccumulateOffsets(5058          A, *this, &V, DL, Offset, /* GetMinOffset */ false,5059          /* AllowNonInbounds */ true);5060 5061      const auto *AA = A.getAAFor<AADereferenceable>(5062          *this, IRPosition::value(*Base), DepClassTy::REQUIRED);5063      int64_t DerefBytes = 0;5064      if (!AA || (!Stripped && this == AA)) {5065        // Use IR information if we did not strip anything.5066        // TODO: track globally.5067        bool CanBeNull, CanBeFreed;5068        DerefBytes =5069            Base->getPointerDereferenceableBytes(DL, CanBeNull, CanBeFreed);5070        T.GlobalState.indicatePessimisticFixpoint();5071      } else {5072        const DerefState &DS = AA->getState();5073        DerefBytes = DS.DerefBytesState.getAssumed();5074        T.GlobalState &= DS.GlobalState;5075      }5076 5077      // For now we do not try to "increase" dereferenceability due to negative5078      // indices as we first have to come up with code to deal with loops and5079      // for overflows of the dereferenceable bytes.5080      int64_t OffsetSExt = Offset.getSExtValue();5081      if (OffsetSExt < 0)5082        OffsetSExt = 0;5083 5084      T.takeAssumedDerefBytesMinimum(5085          std::max(int64_t(0), DerefBytes - OffsetSExt));5086 5087      if (this == AA) {5088        if (!Stripped) {5089          // If nothing was stripped IR information is all we got.5090          T.takeKnownDerefBytesMaximum(5091              std::max(int64_t(0), DerefBytes - OffsetSExt));5092          T.indicatePessimisticFixpoint();5093        } else if (OffsetSExt > 0) {5094          // If something was stripped but there is circular reasoning we look5095          // for the offset. If it is positive we basically decrease the5096          // dereferenceable bytes in a circular loop now, which will simply5097          // drive them down to the known value in a very slow way which we5098          // can accelerate.5099          T.indicatePessimisticFixpoint();5100        }5101      }5102 5103      return T.isValidState();5104    };5105 5106    for (const auto &VAC : Values)5107      if (!VisitValueCB(*VAC.getValue()))5108        return indicatePessimisticFixpoint();5109 5110    return clampStateAndIndicateChange(getState(), T);5111  }5112 5113  /// See AbstractAttribute::trackStatistics()5114  void trackStatistics() const override {5115    STATS_DECLTRACK_FLOATING_ATTR(dereferenceable)5116  }5117};5118 5119/// Dereferenceable attribute for a return value.5120struct AADereferenceableReturned final5121    : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl> {5122  using Base =5123      AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl>;5124  AADereferenceableReturned(const IRPosition &IRP, Attributor &A)5125      : Base(IRP, A) {}5126 5127  /// See AbstractAttribute::trackStatistics()5128  void trackStatistics() const override {5129    STATS_DECLTRACK_FNRET_ATTR(dereferenceable)5130  }5131};5132 5133/// Dereferenceable attribute for an argument5134struct AADereferenceableArgument final5135    : AAArgumentFromCallSiteArguments<AADereferenceable,5136                                      AADereferenceableImpl> {5137  using Base =5138      AAArgumentFromCallSiteArguments<AADereferenceable, AADereferenceableImpl>;5139  AADereferenceableArgument(const IRPosition &IRP, Attributor &A)5140      : Base(IRP, A) {}5141 5142  /// See AbstractAttribute::trackStatistics()5143  void trackStatistics() const override {5144    STATS_DECLTRACK_ARG_ATTR(dereferenceable)5145  }5146};5147 5148/// Dereferenceable attribute for a call site argument.5149struct AADereferenceableCallSiteArgument final : AADereferenceableFloating {5150  AADereferenceableCallSiteArgument(const IRPosition &IRP, Attributor &A)5151      : AADereferenceableFloating(IRP, A) {}5152 5153  /// See AbstractAttribute::trackStatistics()5154  void trackStatistics() const override {5155    STATS_DECLTRACK_CSARG_ATTR(dereferenceable)5156  }5157};5158 5159/// Dereferenceable attribute deduction for a call site return value.5160struct AADereferenceableCallSiteReturned final5161    : AACalleeToCallSite<AADereferenceable, AADereferenceableImpl> {5162  using Base = AACalleeToCallSite<AADereferenceable, AADereferenceableImpl>;5163  AADereferenceableCallSiteReturned(const IRPosition &IRP, Attributor &A)5164      : Base(IRP, A) {}5165 5166  /// See AbstractAttribute::trackStatistics()5167  void trackStatistics() const override {5168    STATS_DECLTRACK_CS_ATTR(dereferenceable);5169  }5170};5171} // namespace5172 5173// ------------------------ Align Argument Attribute ------------------------5174 5175namespace {5176 5177static unsigned getKnownAlignForUse(Attributor &A, AAAlign &QueryingAA,5178                                    Value &AssociatedValue, const Use *U,5179                                    const Instruction *I, bool &TrackUse) {5180  // We need to follow common pointer manipulation uses to the accesses they5181  // feed into.5182  if (isa<CastInst>(I)) {5183    // Follow all but ptr2int casts.5184    TrackUse = !isa<PtrToIntInst>(I);5185    return 0;5186  }5187  if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) {5188    if (GEP->hasAllConstantIndices())5189      TrackUse = true;5190    return 0;5191  }5192  if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I))5193    switch (II->getIntrinsicID()) {5194    case Intrinsic::ptrmask: {5195      // Is it appropriate to pull attribute in initialization?5196      const auto *ConstVals = A.getAAFor<AAPotentialConstantValues>(5197          QueryingAA, IRPosition::value(*II->getOperand(1)), DepClassTy::NONE);5198      const auto *AlignAA = A.getAAFor<AAAlign>(5199          QueryingAA, IRPosition::value(*II), DepClassTy::NONE);5200      if (ConstVals && ConstVals->isValidState() && ConstVals->isAtFixpoint()) {5201        unsigned ShiftValue = std::min(ConstVals->getAssumedMinTrailingZeros(),5202                                       Value::MaxAlignmentExponent);5203        Align ConstAlign(UINT64_C(1) << ShiftValue);5204        if (ConstAlign >= AlignAA->getKnownAlign())5205          return Align(1).value();5206      }5207      if (AlignAA)5208        return AlignAA->getKnownAlign().value();5209      break;5210    }5211    default:5212      break;5213    }5214 5215  MaybeAlign MA;5216  if (const auto *CB = dyn_cast<CallBase>(I)) {5217    if (CB->isBundleOperand(U) || CB->isCallee(U))5218      return 0;5219 5220    unsigned ArgNo = CB->getArgOperandNo(U);5221    IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);5222    // As long as we only use known information there is no need to track5223    // dependences here.5224    auto *AlignAA = A.getAAFor<AAAlign>(QueryingAA, IRP, DepClassTy::NONE);5225    if (AlignAA)5226      MA = MaybeAlign(AlignAA->getKnownAlign());5227  }5228 5229  const DataLayout &DL = A.getDataLayout();5230  const Value *UseV = U->get();5231  if (auto *SI = dyn_cast<StoreInst>(I)) {5232    if (SI->getPointerOperand() == UseV)5233      MA = SI->getAlign();5234  } else if (auto *LI = dyn_cast<LoadInst>(I)) {5235    if (LI->getPointerOperand() == UseV)5236      MA = LI->getAlign();5237  } else if (auto *AI = dyn_cast<AtomicRMWInst>(I)) {5238    if (AI->getPointerOperand() == UseV)5239      MA = AI->getAlign();5240  } else if (auto *AI = dyn_cast<AtomicCmpXchgInst>(I)) {5241    if (AI->getPointerOperand() == UseV)5242      MA = AI->getAlign();5243  }5244 5245  if (!MA || *MA <= QueryingAA.getKnownAlign())5246    return 0;5247 5248  unsigned Alignment = MA->value();5249  int64_t Offset;5250 5251  if (const Value *Base = GetPointerBaseWithConstantOffset(UseV, Offset, DL)) {5252    if (Base == &AssociatedValue) {5253      // BasePointerAddr + Offset = Alignment * Q for some integer Q.5254      // So we can say that the maximum power of two which is a divisor of5255      // gcd(Offset, Alignment) is an alignment.5256 5257      uint32_t gcd = std::gcd(uint32_t(abs((int32_t)Offset)), Alignment);5258      Alignment = llvm::bit_floor(gcd);5259    }5260  }5261 5262  return Alignment;5263}5264 5265struct AAAlignImpl : AAAlign {5266  AAAlignImpl(const IRPosition &IRP, Attributor &A) : AAAlign(IRP, A) {}5267 5268  /// See AbstractAttribute::initialize(...).5269  void initialize(Attributor &A) override {5270    SmallVector<Attribute, 4> Attrs;5271    A.getAttrs(getIRPosition(), {Attribute::Alignment}, Attrs);5272    for (const Attribute &Attr : Attrs)5273      takeKnownMaximum(Attr.getValueAsInt());5274 5275    Value &V = *getAssociatedValue().stripPointerCasts();5276    takeKnownMaximum(V.getPointerAlignment(A.getDataLayout()).value());5277 5278    if (Instruction *CtxI = getCtxI())5279      followUsesInMBEC(*this, A, getState(), *CtxI);5280  }5281 5282  /// See AbstractAttribute::manifest(...).5283  ChangeStatus manifest(Attributor &A) override {5284    ChangeStatus InstrChanged = ChangeStatus::UNCHANGED;5285 5286    // Check for users that allow alignment annotations.5287    Value &AssociatedValue = getAssociatedValue();5288    if (isa<ConstantData>(AssociatedValue))5289      return ChangeStatus::UNCHANGED;5290 5291    for (const Use &U : AssociatedValue.uses()) {5292      if (auto *SI = dyn_cast<StoreInst>(U.getUser())) {5293        if (SI->getPointerOperand() == &AssociatedValue)5294          if (SI->getAlign() < getAssumedAlign()) {5295            STATS_DECLTRACK(AAAlign, Store,5296                            "Number of times alignment added to a store");5297            SI->setAlignment(getAssumedAlign());5298            InstrChanged = ChangeStatus::CHANGED;5299          }5300      } else if (auto *LI = dyn_cast<LoadInst>(U.getUser())) {5301        if (LI->getPointerOperand() == &AssociatedValue)5302          if (LI->getAlign() < getAssumedAlign()) {5303            LI->setAlignment(getAssumedAlign());5304            STATS_DECLTRACK(AAAlign, Load,5305                            "Number of times alignment added to a load");5306            InstrChanged = ChangeStatus::CHANGED;5307          }5308      } else if (auto *RMW = dyn_cast<AtomicRMWInst>(U.getUser())) {5309        if (RMW->getPointerOperand() == &AssociatedValue) {5310          if (RMW->getAlign() < getAssumedAlign()) {5311            STATS_DECLTRACK(AAAlign, AtomicRMW,5312                            "Number of times alignment added to atomicrmw");5313 5314            RMW->setAlignment(getAssumedAlign());5315            InstrChanged = ChangeStatus::CHANGED;5316          }5317        }5318      } else if (auto *CAS = dyn_cast<AtomicCmpXchgInst>(U.getUser())) {5319        if (CAS->getPointerOperand() == &AssociatedValue) {5320          if (CAS->getAlign() < getAssumedAlign()) {5321            STATS_DECLTRACK(AAAlign, AtomicCmpXchg,5322                            "Number of times alignment added to cmpxchg");5323            CAS->setAlignment(getAssumedAlign());5324            InstrChanged = ChangeStatus::CHANGED;5325          }5326        }5327      }5328    }5329 5330    ChangeStatus Changed = AAAlign::manifest(A);5331 5332    Align InheritAlign =5333        getAssociatedValue().getPointerAlignment(A.getDataLayout());5334    if (InheritAlign >= getAssumedAlign())5335      return InstrChanged;5336    return Changed | InstrChanged;5337  }5338 5339  // TODO: Provide a helper to determine the implied ABI alignment and check in5340  //       the existing manifest method and a new one for AAAlignImpl that value5341  //       to avoid making the alignment explicit if it did not improve.5342 5343  /// See AbstractAttribute::getDeducedAttributes5344  void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,5345                            SmallVectorImpl<Attribute> &Attrs) const override {5346    if (getAssumedAlign() > 1)5347      Attrs.emplace_back(5348          Attribute::getWithAlignment(Ctx, Align(getAssumedAlign())));5349  }5350 5351  /// See followUsesInMBEC5352  bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,5353                       AAAlign::StateType &State) {5354    bool TrackUse = false;5355 5356    unsigned int KnownAlign =5357        getKnownAlignForUse(A, *this, getAssociatedValue(), U, I, TrackUse);5358    State.takeKnownMaximum(KnownAlign);5359 5360    return TrackUse;5361  }5362 5363  /// See AbstractAttribute::getAsStr().5364  const std::string getAsStr(Attributor *A) const override {5365    return "align<" + std::to_string(getKnownAlign().value()) + "-" +5366           std::to_string(getAssumedAlign().value()) + ">";5367  }5368};5369 5370/// Align attribute for a floating value.5371struct AAAlignFloating : AAAlignImpl {5372  AAAlignFloating(const IRPosition &IRP, Attributor &A) : AAAlignImpl(IRP, A) {}5373 5374  /// See AbstractAttribute::updateImpl(...).5375  ChangeStatus updateImpl(Attributor &A) override {5376    const DataLayout &DL = A.getDataLayout();5377 5378    bool Stripped;5379    bool UsedAssumedInformation = false;5380    SmallVector<AA::ValueAndContext> Values;5381    if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,5382                                      AA::AnyScope, UsedAssumedInformation)) {5383      Values.push_back({getAssociatedValue(), getCtxI()});5384      Stripped = false;5385    } else {5386      Stripped = Values.size() != 1 ||5387                 Values.front().getValue() != &getAssociatedValue();5388    }5389 5390    StateType T;5391    auto VisitValueCB = [&](Value &V) -> bool {5392      if (isa<UndefValue>(V) || isa<ConstantPointerNull>(V))5393        return true;5394      const auto *AA = A.getAAFor<AAAlign>(*this, IRPosition::value(V),5395                                           DepClassTy::REQUIRED);5396      if (!AA || (!Stripped && this == AA)) {5397        int64_t Offset;5398        unsigned Alignment = 1;5399        if (const Value *Base =5400                GetPointerBaseWithConstantOffset(&V, Offset, DL)) {5401          // TODO: Use AAAlign for the base too.5402          Align PA = Base->getPointerAlignment(DL);5403          // BasePointerAddr + Offset = Alignment * Q for some integer Q.5404          // So we can say that the maximum power of two which is a divisor of5405          // gcd(Offset, Alignment) is an alignment.5406 5407          uint32_t gcd =5408              std::gcd(uint32_t(abs((int32_t)Offset)), uint32_t(PA.value()));5409          Alignment = llvm::bit_floor(gcd);5410        } else {5411          Alignment = V.getPointerAlignment(DL).value();5412        }5413        // Use only IR information if we did not strip anything.5414        T.takeKnownMaximum(Alignment);5415        T.indicatePessimisticFixpoint();5416      } else {5417        // Use abstract attribute information.5418        const AAAlign::StateType &DS = AA->getState();5419        T ^= DS;5420      }5421      return T.isValidState();5422    };5423 5424    for (const auto &VAC : Values) {5425      if (!VisitValueCB(*VAC.getValue()))5426        return indicatePessimisticFixpoint();5427    }5428 5429    //  TODO: If we know we visited all incoming values, thus no are assumed5430    //  dead, we can take the known information from the state T.5431    return clampStateAndIndicateChange(getState(), T);5432  }5433 5434  /// See AbstractAttribute::trackStatistics()5435  void trackStatistics() const override { STATS_DECLTRACK_FLOATING_ATTR(align) }5436};5437 5438/// Align attribute for function return value.5439struct AAAlignReturned final5440    : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl> {5441  using Base = AAReturnedFromReturnedValues<AAAlign, AAAlignImpl>;5442  AAAlignReturned(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}5443 5444  /// See AbstractAttribute::trackStatistics()5445  void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(aligned) }5446};5447 5448/// Align attribute for function argument.5449struct AAAlignArgument final5450    : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl> {5451  using Base = AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl>;5452  AAAlignArgument(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}5453 5454  /// See AbstractAttribute::manifest(...).5455  ChangeStatus manifest(Attributor &A) override {5456    // If the associated argument is involved in a must-tail call we give up5457    // because we would need to keep the argument alignments of caller and5458    // callee in-sync. Just does not seem worth the trouble right now.5459    if (A.getInfoCache().isInvolvedInMustTailCall(*getAssociatedArgument()))5460      return ChangeStatus::UNCHANGED;5461    return Base::manifest(A);5462  }5463 5464  /// See AbstractAttribute::trackStatistics()5465  void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(aligned) }5466};5467 5468struct AAAlignCallSiteArgument final : AAAlignFloating {5469  AAAlignCallSiteArgument(const IRPosition &IRP, Attributor &A)5470      : AAAlignFloating(IRP, A) {}5471 5472  /// See AbstractAttribute::manifest(...).5473  ChangeStatus manifest(Attributor &A) override {5474    // If the associated argument is involved in a must-tail call we give up5475    // because we would need to keep the argument alignments of caller and5476    // callee in-sync. Just does not seem worth the trouble right now.5477    if (Argument *Arg = getAssociatedArgument())5478      if (A.getInfoCache().isInvolvedInMustTailCall(*Arg))5479        return ChangeStatus::UNCHANGED;5480    ChangeStatus Changed = AAAlignImpl::manifest(A);5481    Align InheritAlign =5482        getAssociatedValue().getPointerAlignment(A.getDataLayout());5483    if (InheritAlign >= getAssumedAlign())5484      Changed = ChangeStatus::UNCHANGED;5485    return Changed;5486  }5487 5488  /// See AbstractAttribute::updateImpl(Attributor &A).5489  ChangeStatus updateImpl(Attributor &A) override {5490    ChangeStatus Changed = AAAlignFloating::updateImpl(A);5491    if (Argument *Arg = getAssociatedArgument()) {5492      // We only take known information from the argument5493      // so we do not need to track a dependence.5494      const auto *ArgAlignAA = A.getAAFor<AAAlign>(5495          *this, IRPosition::argument(*Arg), DepClassTy::NONE);5496      if (ArgAlignAA)5497        takeKnownMaximum(ArgAlignAA->getKnownAlign().value());5498    }5499    return Changed;5500  }5501 5502  /// See AbstractAttribute::trackStatistics()5503  void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(aligned) }5504};5505 5506/// Align attribute deduction for a call site return value.5507struct AAAlignCallSiteReturned final5508    : AACalleeToCallSite<AAAlign, AAAlignImpl> {5509  using Base = AACalleeToCallSite<AAAlign, AAAlignImpl>;5510  AAAlignCallSiteReturned(const IRPosition &IRP, Attributor &A)5511      : Base(IRP, A) {}5512 5513  ChangeStatus updateImpl(Attributor &A) override {5514    Instruction *I = getIRPosition().getCtxI();5515    if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {5516      switch (II->getIntrinsicID()) {5517      case Intrinsic::ptrmask: {5518        Align Alignment;5519        bool Valid = false;5520 5521        const auto *ConstVals = A.getAAFor<AAPotentialConstantValues>(5522            *this, IRPosition::value(*II->getOperand(1)), DepClassTy::REQUIRED);5523        if (ConstVals && ConstVals->isValidState()) {5524          unsigned ShiftValue =5525              std::min(ConstVals->getAssumedMinTrailingZeros(),5526                       Value::MaxAlignmentExponent);5527          Alignment = Align(UINT64_C(1) << ShiftValue);5528          Valid = true;5529        }5530 5531        const auto *AlignAA =5532            A.getAAFor<AAAlign>(*this, IRPosition::value(*(II->getOperand(0))),5533                                DepClassTy::REQUIRED);5534        if (AlignAA && AlignAA->isValidState()) {5535          Alignment = std::max(AlignAA->getAssumedAlign(), Alignment);5536          Valid = true;5537        }5538 5539        if (Valid)5540          return clampStateAndIndicateChange<StateType>(5541              this->getState(),5542              std::min(this->getAssumedAlign(), Alignment).value());5543        break;5544      }5545      default:5546        break;5547      }5548    }5549    return Base::updateImpl(A);5550  };5551  /// See AbstractAttribute::trackStatistics()5552  void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(align); }5553};5554} // namespace5555 5556/// ------------------ Function No-Return Attribute ----------------------------5557namespace {5558struct AANoReturnImpl : public AANoReturn {5559  AANoReturnImpl(const IRPosition &IRP, Attributor &A) : AANoReturn(IRP, A) {}5560 5561  /// See AbstractAttribute::initialize(...).5562  void initialize(Attributor &A) override {5563    bool IsKnown;5564    assert(!AA::hasAssumedIRAttr<Attribute::NoReturn>(5565        A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));5566    (void)IsKnown;5567  }5568 5569  /// See AbstractAttribute::getAsStr().5570  const std::string getAsStr(Attributor *A) const override {5571    return getAssumed() ? "noreturn" : "may-return";5572  }5573 5574  /// See AbstractAttribute::updateImpl(Attributor &A).5575  ChangeStatus updateImpl(Attributor &A) override {5576    auto CheckForNoReturn = [](Instruction &) { return false; };5577    bool UsedAssumedInformation = false;5578    if (!A.checkForAllInstructions(CheckForNoReturn, *this,5579                                   {(unsigned)Instruction::Ret},5580                                   UsedAssumedInformation))5581      return indicatePessimisticFixpoint();5582    return ChangeStatus::UNCHANGED;5583  }5584};5585 5586struct AANoReturnFunction final : AANoReturnImpl {5587  AANoReturnFunction(const IRPosition &IRP, Attributor &A)5588      : AANoReturnImpl(IRP, A) {}5589 5590  /// See AbstractAttribute::trackStatistics()5591  void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(noreturn) }5592};5593 5594/// NoReturn attribute deduction for a call sites.5595struct AANoReturnCallSite final5596    : AACalleeToCallSite<AANoReturn, AANoReturnImpl> {5597  AANoReturnCallSite(const IRPosition &IRP, Attributor &A)5598      : AACalleeToCallSite<AANoReturn, AANoReturnImpl>(IRP, A) {}5599 5600  /// See AbstractAttribute::trackStatistics()5601  void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(noreturn); }5602};5603} // namespace5604 5605/// ----------------------- Instance Info ---------------------------------5606 5607namespace {5608/// A class to hold the state of for no-capture attributes.5609struct AAInstanceInfoImpl : public AAInstanceInfo {5610  AAInstanceInfoImpl(const IRPosition &IRP, Attributor &A)5611      : AAInstanceInfo(IRP, A) {}5612 5613  /// See AbstractAttribute::initialize(...).5614  void initialize(Attributor &A) override {5615    Value &V = getAssociatedValue();5616    if (auto *C = dyn_cast<Constant>(&V)) {5617      if (C->isThreadDependent())5618        indicatePessimisticFixpoint();5619      else5620        indicateOptimisticFixpoint();5621      return;5622    }5623    if (auto *CB = dyn_cast<CallBase>(&V))5624      if (CB->arg_size() == 0 && !CB->mayHaveSideEffects() &&5625          !CB->mayReadFromMemory()) {5626        indicateOptimisticFixpoint();5627        return;5628      }5629    if (auto *I = dyn_cast<Instruction>(&V)) {5630      const auto *CI =5631          A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(5632              *I->getFunction());5633      if (mayBeInCycle(CI, I, /* HeaderOnly */ false)) {5634        indicatePessimisticFixpoint();5635        return;5636      }5637    }5638  }5639 5640  /// See AbstractAttribute::updateImpl(...).5641  ChangeStatus updateImpl(Attributor &A) override {5642    ChangeStatus Changed = ChangeStatus::UNCHANGED;5643 5644    Value &V = getAssociatedValue();5645    const Function *Scope = nullptr;5646    if (auto *I = dyn_cast<Instruction>(&V))5647      Scope = I->getFunction();5648    if (auto *A = dyn_cast<Argument>(&V)) {5649      Scope = A->getParent();5650      if (!Scope->hasLocalLinkage())5651        return Changed;5652    }5653    if (!Scope)5654      return indicateOptimisticFixpoint();5655 5656    bool IsKnownNoRecurse;5657    if (AA::hasAssumedIRAttr<Attribute::NoRecurse>(5658            A, this, IRPosition::function(*Scope), DepClassTy::OPTIONAL,5659            IsKnownNoRecurse))5660      return Changed;5661 5662    auto UsePred = [&](const Use &U, bool &Follow) {5663      const Instruction *UserI = dyn_cast<Instruction>(U.getUser());5664      if (!UserI || isa<GetElementPtrInst>(UserI) || isa<CastInst>(UserI) ||5665          isa<PHINode>(UserI) || isa<SelectInst>(UserI)) {5666        Follow = true;5667        return true;5668      }5669      if (isa<LoadInst>(UserI) || isa<CmpInst>(UserI) ||5670          (isa<StoreInst>(UserI) &&5671           cast<StoreInst>(UserI)->getValueOperand() != U.get()))5672        return true;5673      if (auto *CB = dyn_cast<CallBase>(UserI)) {5674        // This check is not guaranteeing uniqueness but for now that we cannot5675        // end up with two versions of \p U thinking it was one.5676        auto *Callee = dyn_cast_if_present<Function>(CB->getCalledOperand());5677        if (!Callee || !Callee->hasLocalLinkage())5678          return true;5679        if (!CB->isArgOperand(&U))5680          return false;5681        const auto *ArgInstanceInfoAA = A.getAAFor<AAInstanceInfo>(5682            *this, IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U)),5683            DepClassTy::OPTIONAL);5684        if (!ArgInstanceInfoAA ||5685            !ArgInstanceInfoAA->isAssumedUniqueForAnalysis())5686          return false;5687        // If this call base might reach the scope again we might forward the5688        // argument back here. This is very conservative.5689        if (AA::isPotentiallyReachable(5690                A, *CB, *Scope, *this, /* ExclusionSet */ nullptr,5691                [Scope](const Function &Fn) { return &Fn != Scope; }))5692          return false;5693        return true;5694      }5695      return false;5696    };5697 5698    auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {5699      if (auto *SI = dyn_cast<StoreInst>(OldU.getUser())) {5700        auto *Ptr = SI->getPointerOperand()->stripPointerCasts();5701        if ((isa<AllocaInst>(Ptr) || isNoAliasCall(Ptr)) &&5702            AA::isDynamicallyUnique(A, *this, *Ptr))5703          return true;5704      }5705      return false;5706    };5707 5708    if (!A.checkForAllUses(UsePred, *this, V, /* CheckBBLivenessOnly */ true,5709                           DepClassTy::OPTIONAL,5710                           /* IgnoreDroppableUses */ true, EquivalentUseCB))5711      return indicatePessimisticFixpoint();5712 5713    return Changed;5714  }5715 5716  /// See AbstractState::getAsStr().5717  const std::string getAsStr(Attributor *A) const override {5718    return isAssumedUniqueForAnalysis() ? "<unique [fAa]>" : "<unknown>";5719  }5720 5721  /// See AbstractAttribute::trackStatistics()5722  void trackStatistics() const override {}5723};5724 5725/// InstanceInfo attribute for floating values.5726struct AAInstanceInfoFloating : AAInstanceInfoImpl {5727  AAInstanceInfoFloating(const IRPosition &IRP, Attributor &A)5728      : AAInstanceInfoImpl(IRP, A) {}5729};5730 5731/// NoCapture attribute for function arguments.5732struct AAInstanceInfoArgument final : AAInstanceInfoFloating {5733  AAInstanceInfoArgument(const IRPosition &IRP, Attributor &A)5734      : AAInstanceInfoFloating(IRP, A) {}5735};5736 5737/// InstanceInfo attribute for call site arguments.5738struct AAInstanceInfoCallSiteArgument final : AAInstanceInfoImpl {5739  AAInstanceInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)5740      : AAInstanceInfoImpl(IRP, A) {}5741 5742  /// See AbstractAttribute::updateImpl(...).5743  ChangeStatus updateImpl(Attributor &A) override {5744    // TODO: Once we have call site specific value information we can provide5745    //       call site specific liveness information and then it makes5746    //       sense to specialize attributes for call sites arguments instead of5747    //       redirecting requests to the callee argument.5748    Argument *Arg = getAssociatedArgument();5749    if (!Arg)5750      return indicatePessimisticFixpoint();5751    const IRPosition &ArgPos = IRPosition::argument(*Arg);5752    auto *ArgAA =5753        A.getAAFor<AAInstanceInfo>(*this, ArgPos, DepClassTy::REQUIRED);5754    if (!ArgAA)5755      return indicatePessimisticFixpoint();5756    return clampStateAndIndicateChange(getState(), ArgAA->getState());5757  }5758};5759 5760/// InstanceInfo attribute for function return value.5761struct AAInstanceInfoReturned final : AAInstanceInfoImpl {5762  AAInstanceInfoReturned(const IRPosition &IRP, Attributor &A)5763      : AAInstanceInfoImpl(IRP, A) {5764    llvm_unreachable("InstanceInfo is not applicable to function returns!");5765  }5766 5767  /// See AbstractAttribute::initialize(...).5768  void initialize(Attributor &A) override {5769    llvm_unreachable("InstanceInfo is not applicable to function returns!");5770  }5771 5772  /// See AbstractAttribute::updateImpl(...).5773  ChangeStatus updateImpl(Attributor &A) override {5774    llvm_unreachable("InstanceInfo is not applicable to function returns!");5775  }5776};5777 5778/// InstanceInfo attribute deduction for a call site return value.5779struct AAInstanceInfoCallSiteReturned final : AAInstanceInfoFloating {5780  AAInstanceInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)5781      : AAInstanceInfoFloating(IRP, A) {}5782};5783} // namespace5784 5785/// ----------------------- Variable Capturing ---------------------------------5786bool AANoCapture::isImpliedByIR(Attributor &A, const IRPosition &IRP,5787                                Attribute::AttrKind ImpliedAttributeKind,5788                                bool IgnoreSubsumingPositions) {5789  assert(ImpliedAttributeKind == Attribute::Captures &&5790         "Unexpected attribute kind");5791  Value &V = IRP.getAssociatedValue();5792  if (!isa<Constant>(V) && !IRP.isArgumentPosition())5793    return V.use_empty();5794 5795  // You cannot "capture" null in the default address space.5796  //5797  // FIXME: This should use NullPointerIsDefined to account for the function5798  // attribute.5799  if (isa<UndefValue>(V) || (isa<ConstantPointerNull>(V) &&5800                             V.getType()->getPointerAddressSpace() == 0)) {5801    return true;5802  }5803 5804  SmallVector<Attribute, 1> Attrs;5805  A.getAttrs(IRP, {Attribute::Captures}, Attrs,5806             /* IgnoreSubsumingPositions */ true);5807  for (const Attribute &Attr : Attrs)5808    if (capturesNothing(Attr.getCaptureInfo()))5809      return true;5810 5811  if (IRP.getPositionKind() == IRP_CALL_SITE_ARGUMENT)5812    if (Argument *Arg = IRP.getAssociatedArgument()) {5813      SmallVector<Attribute, 1> Attrs;5814      A.getAttrs(IRPosition::argument(*Arg),5815                 {Attribute::Captures, Attribute::ByVal}, Attrs,5816                 /* IgnoreSubsumingPositions */ true);5817      bool ArgNoCapture = any_of(Attrs, [](Attribute Attr) {5818        return Attr.getKindAsEnum() == Attribute::ByVal ||5819               capturesNothing(Attr.getCaptureInfo());5820      });5821      if (ArgNoCapture) {5822        A.manifestAttrs(IRP, Attribute::getWithCaptureInfo(5823                                 V.getContext(), CaptureInfo::none()));5824        return true;5825      }5826    }5827 5828  if (const Function *F = IRP.getAssociatedFunction()) {5829    // Check what state the associated function can actually capture.5830    AANoCapture::StateType State;5831    determineFunctionCaptureCapabilities(IRP, *F, State);5832    if (State.isKnown(NO_CAPTURE)) {5833      A.manifestAttrs(IRP, Attribute::getWithCaptureInfo(V.getContext(),5834                                                         CaptureInfo::none()));5835      return true;5836    }5837  }5838 5839  return false;5840}5841 5842/// Set the NOT_CAPTURED_IN_MEM and NOT_CAPTURED_IN_RET bits in \p Known5843/// depending on the ability of the function associated with \p IRP to capture5844/// state in memory and through "returning/throwing", respectively.5845void AANoCapture::determineFunctionCaptureCapabilities(const IRPosition &IRP,5846                                                       const Function &F,5847                                                       BitIntegerState &State) {5848  // TODO: Once we have memory behavior attributes we should use them here.5849 5850  // If we know we cannot communicate or write to memory, we do not care about5851  // ptr2int anymore.5852  bool ReadOnly = F.onlyReadsMemory();5853  bool NoThrow = F.doesNotThrow();5854  bool IsVoidReturn = F.getReturnType()->isVoidTy();5855  if (ReadOnly && NoThrow && IsVoidReturn) {5856    State.addKnownBits(NO_CAPTURE);5857    return;5858  }5859 5860  // A function cannot capture state in memory if it only reads memory, it can5861  // however return/throw state and the state might be influenced by the5862  // pointer value, e.g., loading from a returned pointer might reveal a bit.5863  if (ReadOnly)5864    State.addKnownBits(NOT_CAPTURED_IN_MEM);5865 5866  // A function cannot communicate state back if it does not through5867  // exceptions and doesn not return values.5868  if (NoThrow && IsVoidReturn)5869    State.addKnownBits(NOT_CAPTURED_IN_RET);5870 5871  // Check existing "returned" attributes.5872  int ArgNo = IRP.getCalleeArgNo();5873  if (!NoThrow || ArgNo < 0 ||5874      !F.getAttributes().hasAttrSomewhere(Attribute::Returned))5875    return;5876 5877  for (unsigned U = 0, E = F.arg_size(); U < E; ++U)5878    if (F.hasParamAttribute(U, Attribute::Returned)) {5879      if (U == unsigned(ArgNo))5880        State.removeAssumedBits(NOT_CAPTURED_IN_RET);5881      else if (ReadOnly)5882        State.addKnownBits(NO_CAPTURE);5883      else5884        State.addKnownBits(NOT_CAPTURED_IN_RET);5885      break;5886    }5887}5888 5889namespace {5890/// A class to hold the state of for no-capture attributes.5891struct AANoCaptureImpl : public AANoCapture {5892  AANoCaptureImpl(const IRPosition &IRP, Attributor &A) : AANoCapture(IRP, A) {}5893 5894  /// See AbstractAttribute::initialize(...).5895  void initialize(Attributor &A) override {5896    bool IsKnown;5897    assert(!AA::hasAssumedIRAttr<Attribute::Captures>(5898        A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));5899    (void)IsKnown;5900  }5901 5902  /// See AbstractAttribute::updateImpl(...).5903  ChangeStatus updateImpl(Attributor &A) override;5904 5905  /// see AbstractAttribute::isAssumedNoCaptureMaybeReturned(...).5906  void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,5907                            SmallVectorImpl<Attribute> &Attrs) const override {5908    if (!isAssumedNoCaptureMaybeReturned())5909      return;5910 5911    if (isArgumentPosition()) {5912      if (isAssumedNoCapture())5913        Attrs.emplace_back(Attribute::get(Ctx, Attribute::Captures));5914      else if (ManifestInternal)5915        Attrs.emplace_back(Attribute::get(Ctx, "no-capture-maybe-returned"));5916    }5917  }5918 5919  /// See AbstractState::getAsStr().5920  const std::string getAsStr(Attributor *A) const override {5921    if (isKnownNoCapture())5922      return "known not-captured";5923    if (isAssumedNoCapture())5924      return "assumed not-captured";5925    if (isKnownNoCaptureMaybeReturned())5926      return "known not-captured-maybe-returned";5927    if (isAssumedNoCaptureMaybeReturned())5928      return "assumed not-captured-maybe-returned";5929    return "assumed-captured";5930  }5931 5932  /// Check the use \p U and update \p State accordingly. Return true if we5933  /// should continue to update the state.5934  bool checkUse(Attributor &A, AANoCapture::StateType &State, const Use &U,5935                bool &Follow) {5936    Instruction *UInst = cast<Instruction>(U.getUser());5937    LLVM_DEBUG(dbgs() << "[AANoCapture] Check use: " << *U.get() << " in "5938                      << *UInst << "\n");5939 5940    // Deal with ptr2int by following uses.5941    if (isa<PtrToIntInst>(UInst)) {5942      LLVM_DEBUG(dbgs() << " - ptr2int assume the worst!\n");5943      return isCapturedIn(State, /* Memory */ true, /* Integer */ true,5944                          /* Return */ true);5945    }5946 5947    // For stores we already checked if we can follow them, if they make it5948    // here we give up.5949    if (isa<StoreInst>(UInst))5950      return isCapturedIn(State, /* Memory */ true, /* Integer */ true,5951                          /* Return */ true);5952 5953    // Explicitly catch return instructions.5954    if (isa<ReturnInst>(UInst)) {5955      if (UInst->getFunction() == getAnchorScope())5956        return isCapturedIn(State, /* Memory */ false, /* Integer */ false,5957                            /* Return */ true);5958      return isCapturedIn(State, /* Memory */ true, /* Integer */ true,5959                          /* Return */ true);5960    }5961 5962    // For now we only use special logic for call sites. However, the tracker5963    // itself knows about a lot of other non-capturing cases already.5964    auto *CB = dyn_cast<CallBase>(UInst);5965    if (!CB || !CB->isArgOperand(&U))5966      return isCapturedIn(State, /* Memory */ true, /* Integer */ true,5967                          /* Return */ true);5968 5969    unsigned ArgNo = CB->getArgOperandNo(&U);5970    const IRPosition &CSArgPos = IRPosition::callsite_argument(*CB, ArgNo);5971    // If we have a abstract no-capture attribute for the argument we can use5972    // it to justify a non-capture attribute here. This allows recursion!5973    bool IsKnownNoCapture;5974    const AANoCapture *ArgNoCaptureAA = nullptr;5975    bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(5976        A, this, CSArgPos, DepClassTy::REQUIRED, IsKnownNoCapture, false,5977        &ArgNoCaptureAA);5978    if (IsAssumedNoCapture)5979      return isCapturedIn(State, /* Memory */ false, /* Integer */ false,5980                          /* Return */ false);5981    if (ArgNoCaptureAA && ArgNoCaptureAA->isAssumedNoCaptureMaybeReturned()) {5982      Follow = true;5983      return isCapturedIn(State, /* Memory */ false, /* Integer */ false,5984                          /* Return */ false);5985    }5986 5987    // Lastly, we could not find a reason no-capture can be assumed so we don't.5988    return isCapturedIn(State, /* Memory */ true, /* Integer */ true,5989                        /* Return */ true);5990  }5991 5992  /// Update \p State according to \p CapturedInMem, \p CapturedInInt, and5993  /// \p CapturedInRet, then return true if we should continue updating the5994  /// state.5995  static bool isCapturedIn(AANoCapture::StateType &State, bool CapturedInMem,5996                           bool CapturedInInt, bool CapturedInRet) {5997    LLVM_DEBUG(dbgs() << " - captures [Mem " << CapturedInMem << "|Int "5998                      << CapturedInInt << "|Ret " << CapturedInRet << "]\n");5999    if (CapturedInMem)6000      State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_MEM);6001    if (CapturedInInt)6002      State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_INT);6003    if (CapturedInRet)6004      State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_RET);6005    return State.isAssumed(AANoCapture::NO_CAPTURE_MAYBE_RETURNED);6006  }6007};6008 6009ChangeStatus AANoCaptureImpl::updateImpl(Attributor &A) {6010  const IRPosition &IRP = getIRPosition();6011  Value *V = isArgumentPosition() ? IRP.getAssociatedArgument()6012                                  : &IRP.getAssociatedValue();6013  if (!V)6014    return indicatePessimisticFixpoint();6015 6016  const Function *F =6017      isArgumentPosition() ? IRP.getAssociatedFunction() : IRP.getAnchorScope();6018 6019  // TODO: Is the checkForAllUses below useful for constants?6020  if (!F)6021    return indicatePessimisticFixpoint();6022 6023  AANoCapture::StateType T;6024  const IRPosition &FnPos = IRPosition::function(*F);6025 6026  // Readonly means we cannot capture through memory.6027  bool IsKnown;6028  if (AA::isAssumedReadOnly(A, FnPos, *this, IsKnown)) {6029    T.addKnownBits(NOT_CAPTURED_IN_MEM);6030    if (IsKnown)6031      addKnownBits(NOT_CAPTURED_IN_MEM);6032  }6033 6034  // Make sure all returned values are different than the underlying value.6035  // TODO: we could do this in a more sophisticated way inside6036  //       AAReturnedValues, e.g., track all values that escape through returns6037  //       directly somehow.6038  auto CheckReturnedArgs = [&](bool &UsedAssumedInformation) {6039    SmallVector<AA::ValueAndContext> Values;6040    if (!A.getAssumedSimplifiedValues(IRPosition::returned(*F), this, Values,6041                                      AA::ValueScope::Intraprocedural,6042                                      UsedAssumedInformation))6043      return false;6044    bool SeenConstant = false;6045    for (const AA::ValueAndContext &VAC : Values) {6046      if (isa<Constant>(VAC.getValue())) {6047        if (SeenConstant)6048          return false;6049        SeenConstant = true;6050      } else if (!isa<Argument>(VAC.getValue()) ||6051                 VAC.getValue() == getAssociatedArgument())6052        return false;6053    }6054    return true;6055  };6056 6057  bool IsKnownNoUnwind;6058  if (AA::hasAssumedIRAttr<Attribute::NoUnwind>(6059          A, this, FnPos, DepClassTy::OPTIONAL, IsKnownNoUnwind)) {6060    bool IsVoidTy = F->getReturnType()->isVoidTy();6061    bool UsedAssumedInformation = false;6062    if (IsVoidTy || CheckReturnedArgs(UsedAssumedInformation)) {6063      T.addKnownBits(NOT_CAPTURED_IN_RET);6064      if (T.isKnown(NOT_CAPTURED_IN_MEM))6065        return ChangeStatus::UNCHANGED;6066      if (IsKnownNoUnwind && (IsVoidTy || !UsedAssumedInformation)) {6067        addKnownBits(NOT_CAPTURED_IN_RET);6068        if (isKnown(NOT_CAPTURED_IN_MEM))6069          return indicateOptimisticFixpoint();6070      }6071    }6072  }6073 6074  auto UseCheck = [&](const Use &U, bool &Follow) -> bool {6075    // TODO(captures): Make this more precise.6076    UseCaptureInfo CI = DetermineUseCaptureKind(U, /*Base=*/nullptr);6077    if (capturesNothing(CI))6078      return true;6079    if (CI.isPassthrough()) {6080      Follow = true;6081      return true;6082    }6083    return checkUse(A, T, U, Follow);6084  };6085 6086  if (!A.checkForAllUses(UseCheck, *this, *V))6087    return indicatePessimisticFixpoint();6088 6089  AANoCapture::StateType &S = getState();6090  auto Assumed = S.getAssumed();6091  S.intersectAssumedBits(T.getAssumed());6092  if (!isAssumedNoCaptureMaybeReturned())6093    return indicatePessimisticFixpoint();6094  return Assumed == S.getAssumed() ? ChangeStatus::UNCHANGED6095                                   : ChangeStatus::CHANGED;6096}6097 6098/// NoCapture attribute for function arguments.6099struct AANoCaptureArgument final : AANoCaptureImpl {6100  AANoCaptureArgument(const IRPosition &IRP, Attributor &A)6101      : AANoCaptureImpl(IRP, A) {}6102 6103  /// See AbstractAttribute::trackStatistics()6104  void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nocapture) }6105};6106 6107/// NoCapture attribute for call site arguments.6108struct AANoCaptureCallSiteArgument final : AANoCaptureImpl {6109  AANoCaptureCallSiteArgument(const IRPosition &IRP, Attributor &A)6110      : AANoCaptureImpl(IRP, A) {}6111 6112  /// See AbstractAttribute::updateImpl(...).6113  ChangeStatus updateImpl(Attributor &A) override {6114    // TODO: Once we have call site specific value information we can provide6115    //       call site specific liveness information and then it makes6116    //       sense to specialize attributes for call sites arguments instead of6117    //       redirecting requests to the callee argument.6118    Argument *Arg = getAssociatedArgument();6119    if (!Arg)6120      return indicatePessimisticFixpoint();6121    const IRPosition &ArgPos = IRPosition::argument(*Arg);6122    bool IsKnownNoCapture;6123    const AANoCapture *ArgAA = nullptr;6124    if (AA::hasAssumedIRAttr<Attribute::Captures>(6125            A, this, ArgPos, DepClassTy::REQUIRED, IsKnownNoCapture, false,6126            &ArgAA))6127      return ChangeStatus::UNCHANGED;6128    if (!ArgAA || !ArgAA->isAssumedNoCaptureMaybeReturned())6129      return indicatePessimisticFixpoint();6130    return clampStateAndIndicateChange(getState(), ArgAA->getState());6131  }6132 6133  /// See AbstractAttribute::trackStatistics()6134  void trackStatistics() const override {6135    STATS_DECLTRACK_CSARG_ATTR(nocapture)6136  };6137};6138 6139/// NoCapture attribute for floating values.6140struct AANoCaptureFloating final : AANoCaptureImpl {6141  AANoCaptureFloating(const IRPosition &IRP, Attributor &A)6142      : AANoCaptureImpl(IRP, A) {}6143 6144  /// See AbstractAttribute::trackStatistics()6145  void trackStatistics() const override {6146    STATS_DECLTRACK_FLOATING_ATTR(nocapture)6147  }6148};6149 6150/// NoCapture attribute for function return value.6151struct AANoCaptureReturned final : AANoCaptureImpl {6152  AANoCaptureReturned(const IRPosition &IRP, Attributor &A)6153      : AANoCaptureImpl(IRP, A) {6154    llvm_unreachable("NoCapture is not applicable to function returns!");6155  }6156 6157  /// See AbstractAttribute::initialize(...).6158  void initialize(Attributor &A) override {6159    llvm_unreachable("NoCapture is not applicable to function returns!");6160  }6161 6162  /// See AbstractAttribute::updateImpl(...).6163  ChangeStatus updateImpl(Attributor &A) override {6164    llvm_unreachable("NoCapture is not applicable to function returns!");6165  }6166 6167  /// See AbstractAttribute::trackStatistics()6168  void trackStatistics() const override {}6169};6170 6171/// NoCapture attribute deduction for a call site return value.6172struct AANoCaptureCallSiteReturned final : AANoCaptureImpl {6173  AANoCaptureCallSiteReturned(const IRPosition &IRP, Attributor &A)6174      : AANoCaptureImpl(IRP, A) {}6175 6176  /// See AbstractAttribute::initialize(...).6177  void initialize(Attributor &A) override {6178    const Function *F = getAnchorScope();6179    // Check what state the associated function can actually capture.6180    determineFunctionCaptureCapabilities(getIRPosition(), *F, *this);6181  }6182 6183  /// See AbstractAttribute::trackStatistics()6184  void trackStatistics() const override {6185    STATS_DECLTRACK_CSRET_ATTR(nocapture)6186  }6187};6188} // namespace6189 6190/// ------------------ Value Simplify Attribute ----------------------------6191 6192bool ValueSimplifyStateType::unionAssumed(std::optional<Value *> Other) {6193  // FIXME: Add a typecast support.6194  SimplifiedAssociatedValue = AA::combineOptionalValuesInAAValueLatice(6195      SimplifiedAssociatedValue, Other, Ty);6196  if (SimplifiedAssociatedValue == std::optional<Value *>(nullptr))6197    return false;6198 6199  LLVM_DEBUG({6200    if (SimplifiedAssociatedValue)6201      dbgs() << "[ValueSimplify] is assumed to be "6202             << **SimplifiedAssociatedValue << "\n";6203    else6204      dbgs() << "[ValueSimplify] is assumed to be <none>\n";6205  });6206  return true;6207}6208 6209namespace {6210struct AAValueSimplifyImpl : AAValueSimplify {6211  AAValueSimplifyImpl(const IRPosition &IRP, Attributor &A)6212      : AAValueSimplify(IRP, A) {}6213 6214  /// See AbstractAttribute::initialize(...).6215  void initialize(Attributor &A) override {6216    if (getAssociatedValue().getType()->isVoidTy())6217      indicatePessimisticFixpoint();6218    if (A.hasSimplificationCallback(getIRPosition()))6219      indicatePessimisticFixpoint();6220  }6221 6222  /// See AbstractAttribute::getAsStr().6223  const std::string getAsStr(Attributor *A) const override {6224    LLVM_DEBUG({6225      dbgs() << "SAV: " << (bool)SimplifiedAssociatedValue << " ";6226      if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue)6227        dbgs() << "SAV: " << **SimplifiedAssociatedValue << " ";6228    });6229    return isValidState() ? (isAtFixpoint() ? "simplified" : "maybe-simple")6230                          : "not-simple";6231  }6232 6233  /// See AbstractAttribute::trackStatistics()6234  void trackStatistics() const override {}6235 6236  /// See AAValueSimplify::getAssumedSimplifiedValue()6237  std::optional<Value *>6238  getAssumedSimplifiedValue(Attributor &A) const override {6239    return SimplifiedAssociatedValue;6240  }6241 6242  /// Ensure the return value is \p V with type \p Ty, if not possible return6243  /// nullptr. If \p Check is true we will only verify such an operation would6244  /// suceed and return a non-nullptr value if that is the case. No IR is6245  /// generated or modified.6246  static Value *ensureType(Attributor &A, Value &V, Type &Ty, Instruction *CtxI,6247                           bool Check) {6248    if (auto *TypedV = AA::getWithType(V, Ty))6249      return TypedV;6250    if (CtxI && V.getType()->canLosslesslyBitCastTo(&Ty))6251      return Check ? &V6252                   : BitCastInst::CreatePointerBitCastOrAddrSpaceCast(6253                         &V, &Ty, "", CtxI->getIterator());6254    return nullptr;6255  }6256 6257  /// Reproduce \p I with type \p Ty or return nullptr if that is not posisble.6258  /// If \p Check is true we will only verify such an operation would suceed and6259  /// return a non-nullptr value if that is the case. No IR is generated or6260  /// modified.6261  static Value *reproduceInst(Attributor &A,6262                              const AbstractAttribute &QueryingAA,6263                              Instruction &I, Type &Ty, Instruction *CtxI,6264                              bool Check, ValueToValueMapTy &VMap) {6265    assert(CtxI && "Cannot reproduce an instruction without context!");6266    if (Check && (I.mayReadFromMemory() ||6267                  !isSafeToSpeculativelyExecute(&I, CtxI, /* DT */ nullptr,6268                                                /* TLI */ nullptr)))6269      return nullptr;6270    for (Value *Op : I.operands()) {6271      Value *NewOp = reproduceValue(A, QueryingAA, *Op, Ty, CtxI, Check, VMap);6272      if (!NewOp) {6273        assert(Check && "Manifest of new value unexpectedly failed!");6274        return nullptr;6275      }6276      if (!Check)6277        VMap[Op] = NewOp;6278    }6279    if (Check)6280      return &I;6281 6282    Instruction *CloneI = I.clone();6283    // TODO: Try to salvage debug information here.6284    CloneI->setDebugLoc(DebugLoc());6285    VMap[&I] = CloneI;6286    CloneI->insertBefore(CtxI->getIterator());6287    RemapInstruction(CloneI, VMap);6288    return CloneI;6289  }6290 6291  /// Reproduce \p V with type \p Ty or return nullptr if that is not posisble.6292  /// If \p Check is true we will only verify such an operation would suceed and6293  /// return a non-nullptr value if that is the case. No IR is generated or6294  /// modified.6295  static Value *reproduceValue(Attributor &A,6296                               const AbstractAttribute &QueryingAA, Value &V,6297                               Type &Ty, Instruction *CtxI, bool Check,6298                               ValueToValueMapTy &VMap) {6299    if (const auto &NewV = VMap.lookup(&V))6300      return NewV;6301    bool UsedAssumedInformation = false;6302    std::optional<Value *> SimpleV = A.getAssumedSimplified(6303        V, QueryingAA, UsedAssumedInformation, AA::Interprocedural);6304    if (!SimpleV.has_value())6305      return PoisonValue::get(&Ty);6306    Value *EffectiveV = &V;6307    if (*SimpleV)6308      EffectiveV = *SimpleV;6309    if (auto *C = dyn_cast<Constant>(EffectiveV))6310      return C;6311    if (CtxI && AA::isValidAtPosition(AA::ValueAndContext(*EffectiveV, *CtxI),6312                                      A.getInfoCache()))6313      return ensureType(A, *EffectiveV, Ty, CtxI, Check);6314    if (auto *I = dyn_cast<Instruction>(EffectiveV))6315      if (Value *NewV = reproduceInst(A, QueryingAA, *I, Ty, CtxI, Check, VMap))6316        return ensureType(A, *NewV, Ty, CtxI, Check);6317    return nullptr;6318  }6319 6320  /// Return a value we can use as replacement for the associated one, or6321  /// nullptr if we don't have one that makes sense.6322  Value *manifestReplacementValue(Attributor &A, Instruction *CtxI) const {6323    Value *NewV = SimplifiedAssociatedValue6324                      ? *SimplifiedAssociatedValue6325                      : UndefValue::get(getAssociatedType());6326    if (NewV && NewV != &getAssociatedValue()) {6327      ValueToValueMapTy VMap;6328      // First verify we can reprduce the value with the required type at the6329      // context location before we actually start modifying the IR.6330      if (reproduceValue(A, *this, *NewV, *getAssociatedType(), CtxI,6331                         /* CheckOnly */ true, VMap))6332        return reproduceValue(A, *this, *NewV, *getAssociatedType(), CtxI,6333                              /* CheckOnly */ false, VMap);6334    }6335    return nullptr;6336  }6337 6338  /// Helper function for querying AAValueSimplify and updating candidate.6339  /// \param IRP The value position we are trying to unify with SimplifiedValue6340  bool checkAndUpdate(Attributor &A, const AbstractAttribute &QueryingAA,6341                      const IRPosition &IRP, bool Simplify = true) {6342    bool UsedAssumedInformation = false;6343    std::optional<Value *> QueryingValueSimplified = &IRP.getAssociatedValue();6344    if (Simplify)6345      QueryingValueSimplified = A.getAssumedSimplified(6346          IRP, QueryingAA, UsedAssumedInformation, AA::Interprocedural);6347    return unionAssumed(QueryingValueSimplified);6348  }6349 6350  /// Returns a candidate is found or not6351  template <typename AAType> bool askSimplifiedValueFor(Attributor &A) {6352    if (!getAssociatedValue().getType()->isIntegerTy())6353      return false;6354 6355    // This will also pass the call base context.6356    const auto *AA =6357        A.getAAFor<AAType>(*this, getIRPosition(), DepClassTy::NONE);6358    if (!AA)6359      return false;6360 6361    std::optional<Constant *> COpt = AA->getAssumedConstant(A);6362 6363    if (!COpt) {6364      SimplifiedAssociatedValue = std::nullopt;6365      A.recordDependence(*AA, *this, DepClassTy::OPTIONAL);6366      return true;6367    }6368    if (auto *C = *COpt) {6369      SimplifiedAssociatedValue = C;6370      A.recordDependence(*AA, *this, DepClassTy::OPTIONAL);6371      return true;6372    }6373    return false;6374  }6375 6376  bool askSimplifiedValueForOtherAAs(Attributor &A) {6377    if (askSimplifiedValueFor<AAValueConstantRange>(A))6378      return true;6379    if (askSimplifiedValueFor<AAPotentialConstantValues>(A))6380      return true;6381    return false;6382  }6383 6384  /// See AbstractAttribute::manifest(...).6385  ChangeStatus manifest(Attributor &A) override {6386    ChangeStatus Changed = ChangeStatus::UNCHANGED;6387    for (auto &U : getAssociatedValue().uses()) {6388      // Check if we need to adjust the insertion point to make sure the IR is6389      // valid.6390      Instruction *IP = dyn_cast<Instruction>(U.getUser());6391      if (auto *PHI = dyn_cast_or_null<PHINode>(IP))6392        IP = PHI->getIncomingBlock(U)->getTerminator();6393      if (auto *NewV = manifestReplacementValue(A, IP)) {6394        LLVM_DEBUG(dbgs() << "[ValueSimplify] " << getAssociatedValue()6395                          << " -> " << *NewV << " :: " << *this << "\n");6396        if (A.changeUseAfterManifest(U, *NewV))6397          Changed = ChangeStatus::CHANGED;6398      }6399    }6400 6401    return Changed | AAValueSimplify::manifest(A);6402  }6403 6404  /// See AbstractState::indicatePessimisticFixpoint(...).6405  ChangeStatus indicatePessimisticFixpoint() override {6406    SimplifiedAssociatedValue = &getAssociatedValue();6407    return AAValueSimplify::indicatePessimisticFixpoint();6408  }6409};6410 6411struct AAValueSimplifyArgument final : AAValueSimplifyImpl {6412  AAValueSimplifyArgument(const IRPosition &IRP, Attributor &A)6413      : AAValueSimplifyImpl(IRP, A) {}6414 6415  void initialize(Attributor &A) override {6416    AAValueSimplifyImpl::initialize(A);6417    if (A.hasAttr(getIRPosition(),6418                  {Attribute::InAlloca, Attribute::Preallocated,6419                   Attribute::StructRet, Attribute::Nest, Attribute::ByVal},6420                  /* IgnoreSubsumingPositions */ true))6421      indicatePessimisticFixpoint();6422  }6423 6424  /// See AbstractAttribute::updateImpl(...).6425  ChangeStatus updateImpl(Attributor &A) override {6426    // Byval is only replacable if it is readonly otherwise we would write into6427    // the replaced value and not the copy that byval creates implicitly.6428    Argument *Arg = getAssociatedArgument();6429    if (Arg->hasByValAttr()) {6430      // TODO: We probably need to verify synchronization is not an issue, e.g.,6431      //       there is no race by not copying a constant byval.6432      bool IsKnown;6433      if (!AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))6434        return indicatePessimisticFixpoint();6435    }6436 6437    auto Before = SimplifiedAssociatedValue;6438 6439    auto PredForCallSite = [&](AbstractCallSite ACS) {6440      const IRPosition &ACSArgPos =6441          IRPosition::callsite_argument(ACS, getCallSiteArgNo());6442      // Check if a coresponding argument was found or if it is on not6443      // associated (which can happen for callback calls).6444      if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)6445        return false;6446 6447      // Simplify the argument operand explicitly and check if the result is6448      // valid in the current scope. This avoids refering to simplified values6449      // in other functions, e.g., we don't want to say a an argument in a6450      // static function is actually an argument in a different function.6451      bool UsedAssumedInformation = false;6452      std::optional<Constant *> SimpleArgOp =6453          A.getAssumedConstant(ACSArgPos, *this, UsedAssumedInformation);6454      if (!SimpleArgOp)6455        return true;6456      if (!*SimpleArgOp)6457        return false;6458      if (!AA::isDynamicallyUnique(A, *this, **SimpleArgOp))6459        return false;6460      return unionAssumed(*SimpleArgOp);6461    };6462 6463    // Generate a answer specific to a call site context.6464    bool Success;6465    bool UsedAssumedInformation = false;6466    if (hasCallBaseContext() &&6467        getCallBaseContext()->getCalledOperand() == Arg->getParent())6468      Success = PredForCallSite(6469          AbstractCallSite(&getCallBaseContext()->getCalledOperandUse()));6470    else6471      Success = A.checkForAllCallSites(PredForCallSite, *this, true,6472                                       UsedAssumedInformation);6473 6474    if (!Success)6475      if (!askSimplifiedValueForOtherAAs(A))6476        return indicatePessimisticFixpoint();6477 6478    // If a candidate was found in this update, return CHANGED.6479    return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED6480                                               : ChangeStatus ::CHANGED;6481  }6482 6483  /// See AbstractAttribute::trackStatistics()6484  void trackStatistics() const override {6485    STATS_DECLTRACK_ARG_ATTR(value_simplify)6486  }6487};6488 6489struct AAValueSimplifyReturned : AAValueSimplifyImpl {6490  AAValueSimplifyReturned(const IRPosition &IRP, Attributor &A)6491      : AAValueSimplifyImpl(IRP, A) {}6492 6493  /// See AAValueSimplify::getAssumedSimplifiedValue()6494  std::optional<Value *>6495  getAssumedSimplifiedValue(Attributor &A) const override {6496    if (!isValidState())6497      return nullptr;6498    return SimplifiedAssociatedValue;6499  }6500 6501  /// See AbstractAttribute::updateImpl(...).6502  ChangeStatus updateImpl(Attributor &A) override {6503    auto Before = SimplifiedAssociatedValue;6504 6505    auto ReturnInstCB = [&](Instruction &I) {6506      auto &RI = cast<ReturnInst>(I);6507      return checkAndUpdate(6508          A, *this,6509          IRPosition::value(*RI.getReturnValue(), getCallBaseContext()));6510    };6511 6512    bool UsedAssumedInformation = false;6513    if (!A.checkForAllInstructions(ReturnInstCB, *this, {Instruction::Ret},6514                                   UsedAssumedInformation))6515      if (!askSimplifiedValueForOtherAAs(A))6516        return indicatePessimisticFixpoint();6517 6518    // If a candidate was found in this update, return CHANGED.6519    return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED6520                                               : ChangeStatus ::CHANGED;6521  }6522 6523  ChangeStatus manifest(Attributor &A) override {6524    // We queried AAValueSimplify for the returned values so they will be6525    // replaced if a simplified form was found. Nothing to do here.6526    return ChangeStatus::UNCHANGED;6527  }6528 6529  /// See AbstractAttribute::trackStatistics()6530  void trackStatistics() const override {6531    STATS_DECLTRACK_FNRET_ATTR(value_simplify)6532  }6533};6534 6535struct AAValueSimplifyFloating : AAValueSimplifyImpl {6536  AAValueSimplifyFloating(const IRPosition &IRP, Attributor &A)6537      : AAValueSimplifyImpl(IRP, A) {}6538 6539  /// See AbstractAttribute::initialize(...).6540  void initialize(Attributor &A) override {6541    AAValueSimplifyImpl::initialize(A);6542    Value &V = getAnchorValue();6543 6544    // TODO: add other stuffs6545    if (isa<Constant>(V))6546      indicatePessimisticFixpoint();6547  }6548 6549  /// See AbstractAttribute::updateImpl(...).6550  ChangeStatus updateImpl(Attributor &A) override {6551    auto Before = SimplifiedAssociatedValue;6552    if (!askSimplifiedValueForOtherAAs(A))6553      return indicatePessimisticFixpoint();6554 6555    // If a candidate was found in this update, return CHANGED.6556    return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED6557                                               : ChangeStatus ::CHANGED;6558  }6559 6560  /// See AbstractAttribute::trackStatistics()6561  void trackStatistics() const override {6562    STATS_DECLTRACK_FLOATING_ATTR(value_simplify)6563  }6564};6565 6566struct AAValueSimplifyFunction : AAValueSimplifyImpl {6567  AAValueSimplifyFunction(const IRPosition &IRP, Attributor &A)6568      : AAValueSimplifyImpl(IRP, A) {}6569 6570  /// See AbstractAttribute::initialize(...).6571  void initialize(Attributor &A) override {6572    SimplifiedAssociatedValue = nullptr;6573    indicateOptimisticFixpoint();6574  }6575  /// See AbstractAttribute::initialize(...).6576  ChangeStatus updateImpl(Attributor &A) override {6577    llvm_unreachable(6578        "AAValueSimplify(Function|CallSite)::updateImpl will not be called");6579  }6580  /// See AbstractAttribute::trackStatistics()6581  void trackStatistics() const override {6582    STATS_DECLTRACK_FN_ATTR(value_simplify)6583  }6584};6585 6586struct AAValueSimplifyCallSite : AAValueSimplifyFunction {6587  AAValueSimplifyCallSite(const IRPosition &IRP, Attributor &A)6588      : AAValueSimplifyFunction(IRP, A) {}6589  /// See AbstractAttribute::trackStatistics()6590  void trackStatistics() const override {6591    STATS_DECLTRACK_CS_ATTR(value_simplify)6592  }6593};6594 6595struct AAValueSimplifyCallSiteReturned : AAValueSimplifyImpl {6596  AAValueSimplifyCallSiteReturned(const IRPosition &IRP, Attributor &A)6597      : AAValueSimplifyImpl(IRP, A) {}6598 6599  void initialize(Attributor &A) override {6600    AAValueSimplifyImpl::initialize(A);6601    Function *Fn = getAssociatedFunction();6602    assert(Fn && "Did expect an associted function");6603    for (Argument &Arg : Fn->args()) {6604      if (Arg.hasReturnedAttr()) {6605        auto IRP = IRPosition::callsite_argument(*cast<CallBase>(getCtxI()),6606                                                 Arg.getArgNo());6607        if (IRP.getPositionKind() == IRPosition::IRP_CALL_SITE_ARGUMENT &&6608            checkAndUpdate(A, *this, IRP))6609          indicateOptimisticFixpoint();6610        else6611          indicatePessimisticFixpoint();6612        return;6613      }6614    }6615  }6616 6617  /// See AbstractAttribute::updateImpl(...).6618  ChangeStatus updateImpl(Attributor &A) override {6619    return indicatePessimisticFixpoint();6620  }6621 6622  void trackStatistics() const override {6623    STATS_DECLTRACK_CSRET_ATTR(value_simplify)6624  }6625};6626 6627struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating {6628  AAValueSimplifyCallSiteArgument(const IRPosition &IRP, Attributor &A)6629      : AAValueSimplifyFloating(IRP, A) {}6630 6631  /// See AbstractAttribute::manifest(...).6632  ChangeStatus manifest(Attributor &A) override {6633    ChangeStatus Changed = ChangeStatus::UNCHANGED;6634    // TODO: We should avoid simplification duplication to begin with.6635    auto *FloatAA = A.lookupAAFor<AAValueSimplify>(6636        IRPosition::value(getAssociatedValue()), this, DepClassTy::NONE);6637    if (FloatAA && FloatAA->getState().isValidState())6638      return Changed;6639 6640    if (auto *NewV = manifestReplacementValue(A, getCtxI())) {6641      Use &U = cast<CallBase>(&getAnchorValue())6642                   ->getArgOperandUse(getCallSiteArgNo());6643      if (A.changeUseAfterManifest(U, *NewV))6644        Changed = ChangeStatus::CHANGED;6645    }6646 6647    return Changed | AAValueSimplify::manifest(A);6648  }6649 6650  void trackStatistics() const override {6651    STATS_DECLTRACK_CSARG_ATTR(value_simplify)6652  }6653};6654} // namespace6655 6656/// ----------------------- Heap-To-Stack Conversion ---------------------------6657namespace {6658struct AAHeapToStackFunction final : public AAHeapToStack {6659 6660  struct AllocationInfo {6661    /// The call that allocates the memory.6662    CallBase *const CB;6663 6664    /// The library function id for the allocation.6665    LibFunc LibraryFunctionId = NotLibFunc;6666 6667    /// The status wrt. a rewrite.6668    enum {6669      STACK_DUE_TO_USE,6670      STACK_DUE_TO_FREE,6671      INVALID,6672    } Status = STACK_DUE_TO_USE;6673 6674    /// Flag to indicate if we encountered a use that might free this allocation6675    /// but which is not in the deallocation infos.6676    bool HasPotentiallyFreeingUnknownUses = false;6677 6678    /// Flag to indicate that we should place the new alloca in the function6679    /// entry block rather than where the call site (CB) is.6680    bool MoveAllocaIntoEntry = true;6681 6682    /// The set of free calls that use this allocation.6683    SmallSetVector<CallBase *, 1> PotentialFreeCalls{};6684  };6685 6686  struct DeallocationInfo {6687    /// The call that deallocates the memory.6688    CallBase *const CB;6689    /// The value freed by the call.6690    Value *FreedOp;6691 6692    /// Flag to indicate if we don't know all objects this deallocation might6693    /// free.6694    bool MightFreeUnknownObjects = false;6695 6696    /// The set of allocation calls that are potentially freed.6697    SmallSetVector<CallBase *, 1> PotentialAllocationCalls{};6698  };6699 6700  AAHeapToStackFunction(const IRPosition &IRP, Attributor &A)6701      : AAHeapToStack(IRP, A) {}6702 6703  ~AAHeapToStackFunction() override {6704    // Ensure we call the destructor so we release any memory allocated in the6705    // sets.6706    for (auto &It : AllocationInfos)6707      It.second->~AllocationInfo();6708    for (auto &It : DeallocationInfos)6709      It.second->~DeallocationInfo();6710  }6711 6712  void initialize(Attributor &A) override {6713    AAHeapToStack::initialize(A);6714 6715    const Function *F = getAnchorScope();6716    const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);6717 6718    auto AllocationIdentifierCB = [&](Instruction &I) {6719      CallBase *CB = dyn_cast<CallBase>(&I);6720      if (!CB)6721        return true;6722      if (Value *FreedOp = getFreedOperand(CB, TLI)) {6723        DeallocationInfos[CB] = new (A.Allocator) DeallocationInfo{CB, FreedOp};6724        return true;6725      }6726      // To do heap to stack, we need to know that the allocation itself is6727      // removable once uses are rewritten, and that we can initialize the6728      // alloca to the same pattern as the original allocation result.6729      if (isRemovableAlloc(CB, TLI)) {6730        auto *I8Ty = Type::getInt8Ty(CB->getParent()->getContext());6731        if (nullptr != getInitialValueOfAllocation(CB, TLI, I8Ty)) {6732          AllocationInfo *AI = new (A.Allocator) AllocationInfo{CB};6733          AllocationInfos[CB] = AI;6734          if (TLI)6735            TLI->getLibFunc(*CB, AI->LibraryFunctionId);6736        }6737      }6738      return true;6739    };6740 6741    bool UsedAssumedInformation = false;6742    bool Success = A.checkForAllCallLikeInstructions(6743        AllocationIdentifierCB, *this, UsedAssumedInformation,6744        /* CheckBBLivenessOnly */ false,6745        /* CheckPotentiallyDead */ true);6746    (void)Success;6747    assert(Success && "Did not expect the call base visit callback to fail!");6748 6749    Attributor::SimplifictionCallbackTy SCB =6750        [](const IRPosition &, const AbstractAttribute *,6751           bool &) -> std::optional<Value *> { return nullptr; };6752    for (const auto &It : AllocationInfos)6753      A.registerSimplificationCallback(IRPosition::callsite_returned(*It.first),6754                                       SCB);6755    for (const auto &It : DeallocationInfos)6756      A.registerSimplificationCallback(IRPosition::callsite_returned(*It.first),6757                                       SCB);6758  }6759 6760  const std::string getAsStr(Attributor *A) const override {6761    unsigned NumH2SMallocs = 0, NumInvalidMallocs = 0;6762    for (const auto &It : AllocationInfos) {6763      if (It.second->Status == AllocationInfo::INVALID)6764        ++NumInvalidMallocs;6765      else6766        ++NumH2SMallocs;6767    }6768    return "[H2S] Mallocs Good/Bad: " + std::to_string(NumH2SMallocs) + "/" +6769           std::to_string(NumInvalidMallocs);6770  }6771 6772  /// See AbstractAttribute::trackStatistics().6773  void trackStatistics() const override {6774    STATS_DECL(6775        MallocCalls, Function,6776        "Number of malloc/calloc/aligned_alloc calls converted to allocas");6777    for (const auto &It : AllocationInfos)6778      if (It.second->Status != AllocationInfo::INVALID)6779        ++BUILD_STAT_NAME(MallocCalls, Function);6780  }6781 6782  bool isAssumedHeapToStack(const CallBase &CB) const override {6783    if (isValidState())6784      if (AllocationInfo *AI =6785              AllocationInfos.lookup(const_cast<CallBase *>(&CB)))6786        return AI->Status != AllocationInfo::INVALID;6787    return false;6788  }6789 6790  bool isAssumedHeapToStackRemovedFree(CallBase &CB) const override {6791    if (!isValidState())6792      return false;6793 6794    for (const auto &It : AllocationInfos) {6795      AllocationInfo &AI = *It.second;6796      if (AI.Status == AllocationInfo::INVALID)6797        continue;6798 6799      if (AI.PotentialFreeCalls.count(&CB))6800        return true;6801    }6802 6803    return false;6804  }6805 6806  ChangeStatus manifest(Attributor &A) override {6807    assert(getState().isValidState() &&6808           "Attempted to manifest an invalid state!");6809 6810    ChangeStatus HasChanged = ChangeStatus::UNCHANGED;6811    Function *F = getAnchorScope();6812    const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);6813 6814    for (auto &It : AllocationInfos) {6815      AllocationInfo &AI = *It.second;6816      if (AI.Status == AllocationInfo::INVALID)6817        continue;6818 6819      for (CallBase *FreeCall : AI.PotentialFreeCalls) {6820        LLVM_DEBUG(dbgs() << "H2S: Removing free call: " << *FreeCall << "\n");6821        A.deleteAfterManifest(*FreeCall);6822        HasChanged = ChangeStatus::CHANGED;6823      }6824 6825      LLVM_DEBUG(dbgs() << "H2S: Removing malloc-like call: " << *AI.CB6826                        << "\n");6827 6828      auto Remark = [&](OptimizationRemark OR) {6829        LibFunc IsAllocShared;6830        if (TLI->getLibFunc(*AI.CB, IsAllocShared))6831          if (IsAllocShared == LibFunc___kmpc_alloc_shared)6832            return OR << "Moving globalized variable to the stack.";6833        return OR << "Moving memory allocation from the heap to the stack.";6834      };6835      if (AI.LibraryFunctionId == LibFunc___kmpc_alloc_shared)6836        A.emitRemark<OptimizationRemark>(AI.CB, "OMP110", Remark);6837      else6838        A.emitRemark<OptimizationRemark>(AI.CB, "HeapToStack", Remark);6839 6840      const DataLayout &DL = A.getInfoCache().getDL();6841      Value *Size;6842      std::optional<APInt> SizeAPI = getSize(A, *this, AI);6843      if (SizeAPI) {6844        Size = ConstantInt::get(AI.CB->getContext(), *SizeAPI);6845      } else {6846        LLVMContext &Ctx = AI.CB->getContext();6847        ObjectSizeOpts Opts;6848        ObjectSizeOffsetEvaluator Eval(DL, TLI, Ctx, Opts);6849        SizeOffsetValue SizeOffsetPair = Eval.compute(AI.CB);6850        assert(SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown() &&6851               cast<ConstantInt>(SizeOffsetPair.Offset)->isZero());6852        Size = SizeOffsetPair.Size;6853      }6854 6855      BasicBlock::iterator IP = AI.MoveAllocaIntoEntry6856                                    ? F->getEntryBlock().begin()6857                                    : AI.CB->getIterator();6858 6859      Align Alignment(1);6860      if (MaybeAlign RetAlign = AI.CB->getRetAlign())6861        Alignment = std::max(Alignment, *RetAlign);6862      if (Value *Align = getAllocAlignment(AI.CB, TLI)) {6863        std::optional<APInt> AlignmentAPI = getAPInt(A, *this, *Align);6864        assert(AlignmentAPI && AlignmentAPI->getZExtValue() > 0 &&6865               "Expected an alignment during manifest!");6866        Alignment =6867            std::max(Alignment, assumeAligned(AlignmentAPI->getZExtValue()));6868      }6869 6870      // TODO: Hoist the alloca towards the function entry.6871      unsigned AS = DL.getAllocaAddrSpace();6872      Instruction *Alloca =6873          new AllocaInst(Type::getInt8Ty(F->getContext()), AS, Size, Alignment,6874                         AI.CB->getName() + ".h2s", IP);6875 6876      if (Alloca->getType() != AI.CB->getType())6877        Alloca = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(6878            Alloca, AI.CB->getType(), "malloc_cast", AI.CB->getIterator());6879 6880      auto *I8Ty = Type::getInt8Ty(F->getContext());6881      auto *InitVal = getInitialValueOfAllocation(AI.CB, TLI, I8Ty);6882      assert(InitVal &&6883             "Must be able to materialize initial memory state of allocation");6884 6885      A.changeAfterManifest(IRPosition::inst(*AI.CB), *Alloca);6886 6887      if (auto *II = dyn_cast<InvokeInst>(AI.CB)) {6888        auto *NBB = II->getNormalDest();6889        BranchInst::Create(NBB, AI.CB->getParent());6890        A.deleteAfterManifest(*AI.CB);6891      } else {6892        A.deleteAfterManifest(*AI.CB);6893      }6894 6895      // Initialize the alloca with the same value as used by the allocation6896      // function.  We can skip undef as the initial value of an alloc is6897      // undef, and the memset would simply end up being DSEd.6898      if (!isa<UndefValue>(InitVal)) {6899        IRBuilder<> Builder(Alloca->getNextNode());6900        // TODO: Use alignment above if align!=16901        Builder.CreateMemSet(Alloca, InitVal, Size, std::nullopt);6902      }6903      HasChanged = ChangeStatus::CHANGED;6904    }6905 6906    return HasChanged;6907  }6908 6909  std::optional<APInt> getAPInt(Attributor &A, const AbstractAttribute &AA,6910                                Value &V) {6911    bool UsedAssumedInformation = false;6912    std::optional<Constant *> SimpleV =6913        A.getAssumedConstant(V, AA, UsedAssumedInformation);6914    if (!SimpleV)6915      return APInt(64, 0);6916    if (auto *CI = dyn_cast_or_null<ConstantInt>(*SimpleV))6917      return CI->getValue();6918    return std::nullopt;6919  }6920 6921  std::optional<APInt> getSize(Attributor &A, const AbstractAttribute &AA,6922                               AllocationInfo &AI) {6923    auto Mapper = [&](const Value *V) -> const Value * {6924      bool UsedAssumedInformation = false;6925      if (std::optional<Constant *> SimpleV =6926              A.getAssumedConstant(*V, AA, UsedAssumedInformation))6927        if (*SimpleV)6928          return *SimpleV;6929      return V;6930    };6931 6932    const Function *F = getAnchorScope();6933    const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);6934    return getAllocSize(AI.CB, TLI, Mapper);6935  }6936 6937  /// Collection of all malloc-like calls in a function with associated6938  /// information.6939  MapVector<CallBase *, AllocationInfo *> AllocationInfos;6940 6941  /// Collection of all free-like calls in a function with associated6942  /// information.6943  MapVector<CallBase *, DeallocationInfo *> DeallocationInfos;6944 6945  ChangeStatus updateImpl(Attributor &A) override;6946};6947 6948ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &A) {6949  ChangeStatus Changed = ChangeStatus::UNCHANGED;6950  const Function *F = getAnchorScope();6951  const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);6952 6953  const auto *LivenessAA =6954      A.getAAFor<AAIsDead>(*this, IRPosition::function(*F), DepClassTy::NONE);6955 6956  MustBeExecutedContextExplorer *Explorer =6957      A.getInfoCache().getMustBeExecutedContextExplorer();6958 6959  bool StackIsAccessibleByOtherThreads =6960      A.getInfoCache().stackIsAccessibleByOtherThreads();6961 6962  LoopInfo *LI =6963      A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(*F);6964  std::optional<bool> MayContainIrreducibleControl;6965  auto IsInLoop = [&](BasicBlock &BB) {6966    if (&F->getEntryBlock() == &BB)6967      return false;6968    if (!MayContainIrreducibleControl.has_value())6969      MayContainIrreducibleControl = mayContainIrreducibleControl(*F, LI);6970    if (*MayContainIrreducibleControl)6971      return true;6972    if (!LI)6973      return true;6974    return LI->getLoopFor(&BB) != nullptr;6975  };6976 6977  // Flag to ensure we update our deallocation information at most once per6978  // updateImpl call and only if we use the free check reasoning.6979  bool HasUpdatedFrees = false;6980 6981  auto UpdateFrees = [&]() {6982    HasUpdatedFrees = true;6983 6984    for (auto &It : DeallocationInfos) {6985      DeallocationInfo &DI = *It.second;6986      // For now we cannot use deallocations that have unknown inputs, skip6987      // them.6988      if (DI.MightFreeUnknownObjects)6989        continue;6990 6991      // No need to analyze dead calls, ignore them instead.6992      bool UsedAssumedInformation = false;6993      if (A.isAssumedDead(*DI.CB, this, LivenessAA, UsedAssumedInformation,6994                          /* CheckBBLivenessOnly */ true))6995        continue;6996 6997      // Use the non-optimistic version to get the freed object.6998      Value *Obj = getUnderlyingObject(DI.FreedOp);6999      if (!Obj) {7000        LLVM_DEBUG(dbgs() << "[H2S] Unknown underlying object for free!\n");7001        DI.MightFreeUnknownObjects = true;7002        continue;7003      }7004 7005      // Free of null and undef can be ignored as no-ops (or UB in the latter7006      // case).7007      if (isa<ConstantPointerNull>(Obj) || isa<UndefValue>(Obj))7008        continue;7009 7010      CallBase *ObjCB = dyn_cast<CallBase>(Obj);7011      if (!ObjCB) {7012        LLVM_DEBUG(dbgs() << "[H2S] Free of a non-call object: " << *Obj7013                          << "\n");7014        DI.MightFreeUnknownObjects = true;7015        continue;7016      }7017 7018      AllocationInfo *AI = AllocationInfos.lookup(ObjCB);7019      if (!AI) {7020        LLVM_DEBUG(dbgs() << "[H2S] Free of a non-allocation object: " << *Obj7021                          << "\n");7022        DI.MightFreeUnknownObjects = true;7023        continue;7024      }7025 7026      DI.PotentialAllocationCalls.insert(ObjCB);7027    }7028  };7029 7030  auto FreeCheck = [&](AllocationInfo &AI) {7031    // If the stack is not accessible by other threads, the "must-free" logic7032    // doesn't apply as the pointer could be shared and needs to be places in7033    // "shareable" memory.7034    if (!StackIsAccessibleByOtherThreads) {7035      bool IsKnownNoSycn;7036      if (!AA::hasAssumedIRAttr<Attribute::NoSync>(7037              A, this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNoSycn)) {7038        LLVM_DEBUG(7039            dbgs() << "[H2S] found an escaping use, stack is not accessible by "7040                      "other threads and function is not nosync:\n");7041        return false;7042      }7043    }7044    if (!HasUpdatedFrees)7045      UpdateFrees();7046 7047    // TODO: Allow multi exit functions that have different free calls.7048    if (AI.PotentialFreeCalls.size() != 1) {7049      LLVM_DEBUG(dbgs() << "[H2S] did not find one free call but "7050                        << AI.PotentialFreeCalls.size() << "\n");7051      return false;7052    }7053    CallBase *UniqueFree = *AI.PotentialFreeCalls.begin();7054    DeallocationInfo *DI = DeallocationInfos.lookup(UniqueFree);7055    if (!DI) {7056      LLVM_DEBUG(7057          dbgs() << "[H2S] unique free call was not known as deallocation call "7058                 << *UniqueFree << "\n");7059      return false;7060    }7061    if (DI->MightFreeUnknownObjects) {7062      LLVM_DEBUG(7063          dbgs() << "[H2S] unique free call might free unknown allocations\n");7064      return false;7065    }7066    if (DI->PotentialAllocationCalls.empty())7067      return true;7068    if (DI->PotentialAllocationCalls.size() > 1) {7069      LLVM_DEBUG(dbgs() << "[H2S] unique free call might free "7070                        << DI->PotentialAllocationCalls.size()7071                        << " different allocations\n");7072      return false;7073    }7074    if (*DI->PotentialAllocationCalls.begin() != AI.CB) {7075      LLVM_DEBUG(7076          dbgs()7077          << "[H2S] unique free call not known to free this allocation but "7078          << **DI->PotentialAllocationCalls.begin() << "\n");7079      return false;7080    }7081 7082    // __kmpc_alloc_shared and __kmpc_alloc_free are by construction matched.7083    if (AI.LibraryFunctionId != LibFunc___kmpc_alloc_shared) {7084      Instruction *CtxI = isa<InvokeInst>(AI.CB) ? AI.CB : AI.CB->getNextNode();7085      if (!Explorer || !Explorer->findInContextOf(UniqueFree, CtxI)) {7086        LLVM_DEBUG(dbgs() << "[H2S] unique free call might not be executed "7087                             "with the allocation "7088                          << *UniqueFree << "\n");7089        return false;7090      }7091    }7092    return true;7093  };7094 7095  auto UsesCheck = [&](AllocationInfo &AI) {7096    bool ValidUsesOnly = true;7097 7098    auto Pred = [&](const Use &U, bool &Follow) -> bool {7099      Instruction *UserI = cast<Instruction>(U.getUser());7100      if (isa<LoadInst>(UserI))7101        return true;7102      if (auto *SI = dyn_cast<StoreInst>(UserI)) {7103        if (SI->getValueOperand() == U.get()) {7104          LLVM_DEBUG(dbgs()7105                     << "[H2S] escaping store to memory: " << *UserI << "\n");7106          ValidUsesOnly = false;7107        } else {7108          // A store into the malloc'ed memory is fine.7109        }7110        return true;7111      }7112      if (auto *CB = dyn_cast<CallBase>(UserI)) {7113        if (!CB->isArgOperand(&U) || CB->isLifetimeStartOrEnd())7114          return true;7115        if (DeallocationInfos.count(CB)) {7116          AI.PotentialFreeCalls.insert(CB);7117          return true;7118        }7119 7120        unsigned ArgNo = CB->getArgOperandNo(&U);7121        auto CBIRP = IRPosition::callsite_argument(*CB, ArgNo);7122 7123        bool IsKnownNoCapture;7124        bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(7125            A, this, CBIRP, DepClassTy::OPTIONAL, IsKnownNoCapture);7126 7127        // If a call site argument use is nofree, we are fine.7128        bool IsKnownNoFree;7129        bool IsAssumedNoFree = AA::hasAssumedIRAttr<Attribute::NoFree>(7130            A, this, CBIRP, DepClassTy::OPTIONAL, IsKnownNoFree);7131 7132        if (!IsAssumedNoCapture ||7133            (AI.LibraryFunctionId != LibFunc___kmpc_alloc_shared &&7134             !IsAssumedNoFree)) {7135          AI.HasPotentiallyFreeingUnknownUses |= !IsAssumedNoFree;7136 7137          // Emit a missed remark if this is missed OpenMP globalization.7138          auto Remark = [&](OptimizationRemarkMissed ORM) {7139            return ORM7140                   << "Could not move globalized variable to the stack. "7141                      "Variable is potentially captured in call. Mark "7142                      "parameter as `__attribute__((noescape))` to override.";7143          };7144 7145          if (ValidUsesOnly &&7146              AI.LibraryFunctionId == LibFunc___kmpc_alloc_shared)7147            A.emitRemark<OptimizationRemarkMissed>(CB, "OMP113", Remark);7148 7149          LLVM_DEBUG(dbgs() << "[H2S] Bad user: " << *UserI << "\n");7150          ValidUsesOnly = false;7151        }7152        return true;7153      }7154 7155      if (isa<GetElementPtrInst>(UserI) || isa<BitCastInst>(UserI) ||7156          isa<PHINode>(UserI) || isa<SelectInst>(UserI)) {7157        Follow = true;7158        return true;7159      }7160      // Unknown user for which we can not track uses further (in a way that7161      // makes sense).7162      LLVM_DEBUG(dbgs() << "[H2S] Unknown user: " << *UserI << "\n");7163      ValidUsesOnly = false;7164      return true;7165    };7166    if (!A.checkForAllUses(Pred, *this, *AI.CB, /* CheckBBLivenessOnly */ false,7167                           DepClassTy::OPTIONAL, /* IgnoreDroppableUses */ true,7168                           [&](const Use &OldU, const Use &NewU) {7169                             auto *SI = dyn_cast<StoreInst>(OldU.getUser());7170                             return !SI || StackIsAccessibleByOtherThreads ||7171                                    AA::isAssumedThreadLocalObject(7172                                        A, *SI->getPointerOperand(), *this);7173                           }))7174      return false;7175    return ValidUsesOnly;7176  };7177 7178  // The actual update starts here. We look at all allocations and depending on7179  // their status perform the appropriate check(s).7180  for (auto &It : AllocationInfos) {7181    AllocationInfo &AI = *It.second;7182    if (AI.Status == AllocationInfo::INVALID)7183      continue;7184 7185    if (Value *Align = getAllocAlignment(AI.CB, TLI)) {7186      std::optional<APInt> APAlign = getAPInt(A, *this, *Align);7187      if (!APAlign) {7188        // Can't generate an alloca which respects the required alignment7189        // on the allocation.7190        LLVM_DEBUG(dbgs() << "[H2S] Unknown allocation alignment: " << *AI.CB7191                          << "\n");7192        AI.Status = AllocationInfo::INVALID;7193        Changed = ChangeStatus::CHANGED;7194        continue;7195      }7196      if (APAlign->ugt(llvm::Value::MaximumAlignment) ||7197          !APAlign->isPowerOf2()) {7198        LLVM_DEBUG(dbgs() << "[H2S] Invalid allocation alignment: " << APAlign7199                          << "\n");7200        AI.Status = AllocationInfo::INVALID;7201        Changed = ChangeStatus::CHANGED;7202        continue;7203      }7204    }7205 7206    std::optional<APInt> Size = getSize(A, *this, AI);7207    if (AI.LibraryFunctionId != LibFunc___kmpc_alloc_shared &&7208        MaxHeapToStackSize != -1) {7209      if (!Size || Size->ugt(MaxHeapToStackSize)) {7210        LLVM_DEBUG({7211          if (!Size)7212            dbgs() << "[H2S] Unknown allocation size: " << *AI.CB << "\n";7213          else7214            dbgs() << "[H2S] Allocation size too large: " << *AI.CB << " vs. "7215                   << MaxHeapToStackSize << "\n";7216        });7217 7218        AI.Status = AllocationInfo::INVALID;7219        Changed = ChangeStatus::CHANGED;7220        continue;7221      }7222    }7223 7224    switch (AI.Status) {7225    case AllocationInfo::STACK_DUE_TO_USE:7226      if (UsesCheck(AI))7227        break;7228      AI.Status = AllocationInfo::STACK_DUE_TO_FREE;7229      [[fallthrough]];7230    case AllocationInfo::STACK_DUE_TO_FREE:7231      if (FreeCheck(AI))7232        break;7233      AI.Status = AllocationInfo::INVALID;7234      Changed = ChangeStatus::CHANGED;7235      break;7236    case AllocationInfo::INVALID:7237      llvm_unreachable("Invalid allocations should never reach this point!");7238    };7239 7240    // Check if we still think we can move it into the entry block. If the7241    // alloca comes from a converted __kmpc_alloc_shared then we can usually7242    // ignore the potential compilations associated with loops.7243    bool IsGlobalizedLocal =7244        AI.LibraryFunctionId == LibFunc___kmpc_alloc_shared;7245    if (AI.MoveAllocaIntoEntry &&7246        (!Size.has_value() ||7247         (!IsGlobalizedLocal && IsInLoop(*AI.CB->getParent()))))7248      AI.MoveAllocaIntoEntry = false;7249  }7250 7251  return Changed;7252}7253} // namespace7254 7255/// ----------------------- Privatizable Pointers ------------------------------7256namespace {7257struct AAPrivatizablePtrImpl : public AAPrivatizablePtr {7258  AAPrivatizablePtrImpl(const IRPosition &IRP, Attributor &A)7259      : AAPrivatizablePtr(IRP, A), PrivatizableType(std::nullopt) {}7260 7261  ChangeStatus indicatePessimisticFixpoint() override {7262    AAPrivatizablePtr::indicatePessimisticFixpoint();7263    PrivatizableType = nullptr;7264    return ChangeStatus::CHANGED;7265  }7266 7267  /// Identify the type we can chose for a private copy of the underlying7268  /// argument. std::nullopt means it is not clear yet, nullptr means there is7269  /// none.7270  virtual std::optional<Type *> identifyPrivatizableType(Attributor &A) = 0;7271 7272  /// Return a privatizable type that encloses both T0 and T1.7273  /// TODO: This is merely a stub for now as we should manage a mapping as well.7274  std::optional<Type *> combineTypes(std::optional<Type *> T0,7275                                     std::optional<Type *> T1) {7276    if (!T0)7277      return T1;7278    if (!T1)7279      return T0;7280    if (T0 == T1)7281      return T0;7282    return nullptr;7283  }7284 7285  std::optional<Type *> getPrivatizableType() const override {7286    return PrivatizableType;7287  }7288 7289  const std::string getAsStr(Attributor *A) const override {7290    return isAssumedPrivatizablePtr() ? "[priv]" : "[no-priv]";7291  }7292 7293protected:7294  std::optional<Type *> PrivatizableType;7295};7296 7297// TODO: Do this for call site arguments (probably also other values) as well.7298 7299struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {7300  AAPrivatizablePtrArgument(const IRPosition &IRP, Attributor &A)7301      : AAPrivatizablePtrImpl(IRP, A) {}7302 7303  /// See AAPrivatizablePtrImpl::identifyPrivatizableType(...)7304  std::optional<Type *> identifyPrivatizableType(Attributor &A) override {7305    // If this is a byval argument and we know all the call sites (so we can7306    // rewrite them), there is no need to check them explicitly.7307    bool UsedAssumedInformation = false;7308    SmallVector<Attribute, 1> Attrs;7309    A.getAttrs(getIRPosition(), {Attribute::ByVal}, Attrs,7310               /* IgnoreSubsumingPositions */ true);7311    if (!Attrs.empty() &&7312        A.checkForAllCallSites([](AbstractCallSite ACS) { return true; }, *this,7313                               true, UsedAssumedInformation))7314      return Attrs[0].getValueAsType();7315 7316    std::optional<Type *> Ty;7317    unsigned ArgNo = getIRPosition().getCallSiteArgNo();7318 7319    // Make sure the associated call site argument has the same type at all call7320    // sites and it is an allocation we know is safe to privatize, for now that7321    // means we only allow alloca instructions.7322    // TODO: We can additionally analyze the accesses in the callee to  create7323    //       the type from that information instead. That is a little more7324    //       involved and will be done in a follow up patch.7325    auto CallSiteCheck = [&](AbstractCallSite ACS) {7326      IRPosition ACSArgPos = IRPosition::callsite_argument(ACS, ArgNo);7327      // Check if a coresponding argument was found or if it is one not7328      // associated (which can happen for callback calls).7329      if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)7330        return false;7331 7332      // Check that all call sites agree on a type.7333      auto *PrivCSArgAA =7334          A.getAAFor<AAPrivatizablePtr>(*this, ACSArgPos, DepClassTy::REQUIRED);7335      if (!PrivCSArgAA)7336        return false;7337      std::optional<Type *> CSTy = PrivCSArgAA->getPrivatizableType();7338 7339      LLVM_DEBUG({7340        dbgs() << "[AAPrivatizablePtr] ACSPos: " << ACSArgPos << ", CSTy: ";7341        if (CSTy && *CSTy)7342          (*CSTy)->print(dbgs());7343        else if (CSTy)7344          dbgs() << "<nullptr>";7345        else7346          dbgs() << "<none>";7347      });7348 7349      Ty = combineTypes(Ty, CSTy);7350 7351      LLVM_DEBUG({7352        dbgs() << " : New Type: ";7353        if (Ty && *Ty)7354          (*Ty)->print(dbgs());7355        else if (Ty)7356          dbgs() << "<nullptr>";7357        else7358          dbgs() << "<none>";7359        dbgs() << "\n";7360      });7361 7362      return !Ty || *Ty;7363    };7364 7365    if (!A.checkForAllCallSites(CallSiteCheck, *this, true,7366                                UsedAssumedInformation))7367      return nullptr;7368    return Ty;7369  }7370 7371  /// See AbstractAttribute::updateImpl(...).7372  ChangeStatus updateImpl(Attributor &A) override {7373    PrivatizableType = identifyPrivatizableType(A);7374    if (!PrivatizableType)7375      return ChangeStatus::UNCHANGED;7376    if (!*PrivatizableType)7377      return indicatePessimisticFixpoint();7378 7379    // The dependence is optional so we don't give up once we give up on the7380    // alignment.7381    A.getAAFor<AAAlign>(*this, IRPosition::value(getAssociatedValue()),7382                        DepClassTy::OPTIONAL);7383 7384    // Avoid arguments with padding for now.7385    if (!A.hasAttr(getIRPosition(), Attribute::ByVal) &&7386        !isDenselyPacked(*PrivatizableType, A.getInfoCache().getDL())) {7387      LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Padding detected\n");7388      return indicatePessimisticFixpoint();7389    }7390 7391    // Collect the types that will replace the privatizable type in the function7392    // signature.7393    SmallVector<Type *, 16> ReplacementTypes;7394    identifyReplacementTypes(*PrivatizableType, ReplacementTypes);7395 7396    // Verify callee and caller agree on how the promoted argument would be7397    // passed.7398    Function &Fn = *getIRPosition().getAnchorScope();7399    const auto *TTI =7400        A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(Fn);7401    if (!TTI) {7402      LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Missing TTI for function "7403                        << Fn.getName() << "\n");7404      return indicatePessimisticFixpoint();7405    }7406 7407    auto CallSiteCheck = [&](AbstractCallSite ACS) {7408      CallBase *CB = ACS.getInstruction();7409      return TTI->areTypesABICompatible(7410          CB->getCaller(),7411          dyn_cast_if_present<Function>(CB->getCalledOperand()),7412          ReplacementTypes);7413    };7414    bool UsedAssumedInformation = false;7415    if (!A.checkForAllCallSites(CallSiteCheck, *this, true,7416                                UsedAssumedInformation)) {7417      LLVM_DEBUG(7418          dbgs() << "[AAPrivatizablePtr] ABI incompatibility detected for "7419                 << Fn.getName() << "\n");7420      return indicatePessimisticFixpoint();7421    }7422 7423    // Register a rewrite of the argument.7424    Argument *Arg = getAssociatedArgument();7425    if (!A.isValidFunctionSignatureRewrite(*Arg, ReplacementTypes)) {7426      LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Rewrite not valid\n");7427      return indicatePessimisticFixpoint();7428    }7429 7430    unsigned ArgNo = Arg->getArgNo();7431 7432    // Helper to check if for the given call site the associated argument is7433    // passed to a callback where the privatization would be different.7434    auto IsCompatiblePrivArgOfCallback = [&](CallBase &CB) {7435      SmallVector<const Use *, 4> CallbackUses;7436      AbstractCallSite::getCallbackUses(CB, CallbackUses);7437      for (const Use *U : CallbackUses) {7438        AbstractCallSite CBACS(U);7439        assert(CBACS && CBACS.isCallbackCall());7440        for (Argument &CBArg : CBACS.getCalledFunction()->args()) {7441          int CBArgNo = CBACS.getCallArgOperandNo(CBArg);7442 7443          LLVM_DEBUG({7444            dbgs()7445                << "[AAPrivatizablePtr] Argument " << *Arg7446                << "check if can be privatized in the context of its parent ("7447                << Arg->getParent()->getName()7448                << ")\n[AAPrivatizablePtr] because it is an argument in a "7449                   "callback ("7450                << CBArgNo << "@" << CBACS.getCalledFunction()->getName()7451                << ")\n[AAPrivatizablePtr] " << CBArg << " : "7452                << CBACS.getCallArgOperand(CBArg) << " vs "7453                << CB.getArgOperand(ArgNo) << "\n"7454                << "[AAPrivatizablePtr] " << CBArg << " : "7455                << CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo << "\n";7456          });7457 7458          if (CBArgNo != int(ArgNo))7459            continue;7460          const auto *CBArgPrivAA = A.getAAFor<AAPrivatizablePtr>(7461              *this, IRPosition::argument(CBArg), DepClassTy::REQUIRED);7462          if (CBArgPrivAA && CBArgPrivAA->isValidState()) {7463            auto CBArgPrivTy = CBArgPrivAA->getPrivatizableType();7464            if (!CBArgPrivTy)7465              continue;7466            if (*CBArgPrivTy == PrivatizableType)7467              continue;7468          }7469 7470          LLVM_DEBUG({7471            dbgs() << "[AAPrivatizablePtr] Argument " << *Arg7472                   << " cannot be privatized in the context of its parent ("7473                   << Arg->getParent()->getName()7474                   << ")\n[AAPrivatizablePtr] because it is an argument in a "7475                      "callback ("7476                   << CBArgNo << "@" << CBACS.getCalledFunction()->getName()7477                   << ").\n[AAPrivatizablePtr] for which the argument "7478                      "privatization is not compatible.\n";7479          });7480          return false;7481        }7482      }7483      return true;7484    };7485 7486    // Helper to check if for the given call site the associated argument is7487    // passed to a direct call where the privatization would be different.7488    auto IsCompatiblePrivArgOfDirectCS = [&](AbstractCallSite ACS) {7489      CallBase *DC = cast<CallBase>(ACS.getInstruction());7490      int DCArgNo = ACS.getCallArgOperandNo(ArgNo);7491      assert(DCArgNo >= 0 && unsigned(DCArgNo) < DC->arg_size() &&7492             "Expected a direct call operand for callback call operand");7493 7494      Function *DCCallee =7495          dyn_cast_if_present<Function>(DC->getCalledOperand());7496      LLVM_DEBUG({7497        dbgs() << "[AAPrivatizablePtr] Argument " << *Arg7498               << " check if be privatized in the context of its parent ("7499               << Arg->getParent()->getName()7500               << ")\n[AAPrivatizablePtr] because it is an argument in a "7501                  "direct call of ("7502               << DCArgNo << "@" << DCCallee->getName() << ").\n";7503      });7504 7505      if (unsigned(DCArgNo) < DCCallee->arg_size()) {7506        const auto *DCArgPrivAA = A.getAAFor<AAPrivatizablePtr>(7507            *this, IRPosition::argument(*DCCallee->getArg(DCArgNo)),7508            DepClassTy::REQUIRED);7509        if (DCArgPrivAA && DCArgPrivAA->isValidState()) {7510          auto DCArgPrivTy = DCArgPrivAA->getPrivatizableType();7511          if (!DCArgPrivTy)7512            return true;7513          if (*DCArgPrivTy == PrivatizableType)7514            return true;7515        }7516      }7517 7518      LLVM_DEBUG({7519        dbgs() << "[AAPrivatizablePtr] Argument " << *Arg7520               << " cannot be privatized in the context of its parent ("7521               << Arg->getParent()->getName()7522               << ")\n[AAPrivatizablePtr] because it is an argument in a "7523                  "direct call of ("7524               << ACS.getInstruction()->getCalledOperand()->getName()7525               << ").\n[AAPrivatizablePtr] for which the argument "7526                  "privatization is not compatible.\n";7527      });7528      return false;7529    };7530 7531    // Helper to check if the associated argument is used at the given abstract7532    // call site in a way that is incompatible with the privatization assumed7533    // here.7534    auto IsCompatiblePrivArgOfOtherCallSite = [&](AbstractCallSite ACS) {7535      if (ACS.isDirectCall())7536        return IsCompatiblePrivArgOfCallback(*ACS.getInstruction());7537      if (ACS.isCallbackCall())7538        return IsCompatiblePrivArgOfDirectCS(ACS);7539      return false;7540    };7541 7542    if (!A.checkForAllCallSites(IsCompatiblePrivArgOfOtherCallSite, *this, true,7543                                UsedAssumedInformation))7544      return indicatePessimisticFixpoint();7545 7546    return ChangeStatus::UNCHANGED;7547  }7548 7549  /// Given a type to private \p PrivType, collect the constituates (which are7550  /// used) in \p ReplacementTypes.7551  static void7552  identifyReplacementTypes(Type *PrivType,7553                           SmallVectorImpl<Type *> &ReplacementTypes) {7554    // TODO: For now we expand the privatization type to the fullest which can7555    //       lead to dead arguments that need to be removed later.7556    assert(PrivType && "Expected privatizable type!");7557 7558    // Traverse the type, extract constituate types on the outermost level.7559    if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {7560      for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++)7561        ReplacementTypes.push_back(PrivStructType->getElementType(u));7562    } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {7563      ReplacementTypes.append(PrivArrayType->getNumElements(),7564                              PrivArrayType->getElementType());7565    } else {7566      ReplacementTypes.push_back(PrivType);7567    }7568  }7569 7570  /// Initialize \p Base according to the type \p PrivType at position \p IP.7571  /// The values needed are taken from the arguments of \p F starting at7572  /// position \p ArgNo.7573  static void createInitialization(Type *PrivType, Value &Base, Function &F,7574                                   unsigned ArgNo, BasicBlock::iterator IP) {7575    assert(PrivType && "Expected privatizable type!");7576 7577    IRBuilder<NoFolder> IRB(IP->getParent(), IP);7578    const DataLayout &DL = F.getDataLayout();7579 7580    // Traverse the type, build GEPs and stores.7581    if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {7582      const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType);7583      for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {7584        Value *Ptr =7585            constructPointer(&Base, PrivStructLayout->getElementOffset(u), IRB);7586        new StoreInst(F.getArg(ArgNo + u), Ptr, IP);7587      }7588    } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {7589      Type *PointeeTy = PrivArrayType->getElementType();7590      uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);7591      for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {7592        Value *Ptr = constructPointer(&Base, u * PointeeTySize, IRB);7593        new StoreInst(F.getArg(ArgNo + u), Ptr, IP);7594      }7595    } else {7596      new StoreInst(F.getArg(ArgNo), &Base, IP);7597    }7598  }7599 7600  /// Extract values from \p Base according to the type \p PrivType at the7601  /// call position \p ACS. The values are appended to \p ReplacementValues.7602  void createReplacementValues(Align Alignment, Type *PrivType,7603                               AbstractCallSite ACS, Value *Base,7604                               SmallVectorImpl<Value *> &ReplacementValues) {7605    assert(Base && "Expected base value!");7606    assert(PrivType && "Expected privatizable type!");7607    Instruction *IP = ACS.getInstruction();7608 7609    IRBuilder<NoFolder> IRB(IP);7610    const DataLayout &DL = IP->getDataLayout();7611 7612    // Traverse the type, build GEPs and loads.7613    if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {7614      const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType);7615      for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {7616        Type *PointeeTy = PrivStructType->getElementType(u);7617        Value *Ptr =7618            constructPointer(Base, PrivStructLayout->getElementOffset(u), IRB);7619        LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP->getIterator());7620        L->setAlignment(Alignment);7621        ReplacementValues.push_back(L);7622      }7623    } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {7624      Type *PointeeTy = PrivArrayType->getElementType();7625      uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);7626      for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {7627        Value *Ptr = constructPointer(Base, u * PointeeTySize, IRB);7628        LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP->getIterator());7629        L->setAlignment(Alignment);7630        ReplacementValues.push_back(L);7631      }7632    } else {7633      LoadInst *L = new LoadInst(PrivType, Base, "", IP->getIterator());7634      L->setAlignment(Alignment);7635      ReplacementValues.push_back(L);7636    }7637  }7638 7639  /// See AbstractAttribute::manifest(...)7640  ChangeStatus manifest(Attributor &A) override {7641    if (!PrivatizableType)7642      return ChangeStatus::UNCHANGED;7643    assert(*PrivatizableType && "Expected privatizable type!");7644 7645    // Collect all tail calls in the function as we cannot allow new allocas to7646    // escape into tail recursion.7647    // TODO: Be smarter about new allocas escaping into tail calls.7648    SmallVector<CallInst *, 16> TailCalls;7649    bool UsedAssumedInformation = false;7650    if (!A.checkForAllInstructions(7651            [&](Instruction &I) {7652              CallInst &CI = cast<CallInst>(I);7653              if (CI.isTailCall())7654                TailCalls.push_back(&CI);7655              return true;7656            },7657            *this, {Instruction::Call}, UsedAssumedInformation))7658      return ChangeStatus::UNCHANGED;7659 7660    Argument *Arg = getAssociatedArgument();7661    // Query AAAlign attribute for alignment of associated argument to7662    // determine the best alignment of loads.7663    const auto *AlignAA =7664        A.getAAFor<AAAlign>(*this, IRPosition::value(*Arg), DepClassTy::NONE);7665 7666    // Callback to repair the associated function. A new alloca is placed at the7667    // beginning and initialized with the values passed through arguments. The7668    // new alloca replaces the use of the old pointer argument.7669    Attributor::ArgumentReplacementInfo::CalleeRepairCBTy FnRepairCB =7670        [=](const Attributor::ArgumentReplacementInfo &ARI,7671            Function &ReplacementFn, Function::arg_iterator ArgIt) {7672          BasicBlock &EntryBB = ReplacementFn.getEntryBlock();7673          BasicBlock::iterator IP = EntryBB.getFirstInsertionPt();7674          const DataLayout &DL = IP->getDataLayout();7675          unsigned AS = DL.getAllocaAddrSpace();7676          Instruction *AI = new AllocaInst(*PrivatizableType, AS,7677                                           Arg->getName() + ".priv", IP);7678          createInitialization(*PrivatizableType, *AI, ReplacementFn,7679                               ArgIt->getArgNo(), IP);7680 7681          if (AI->getType() != Arg->getType())7682            AI = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(7683                AI, Arg->getType(), "", IP);7684          Arg->replaceAllUsesWith(AI);7685 7686          for (CallInst *CI : TailCalls)7687            CI->setTailCall(false);7688        };7689 7690    // Callback to repair a call site of the associated function. The elements7691    // of the privatizable type are loaded prior to the call and passed to the7692    // new function version.7693    Attributor::ArgumentReplacementInfo::ACSRepairCBTy ACSRepairCB =7694        [=](const Attributor::ArgumentReplacementInfo &ARI,7695            AbstractCallSite ACS, SmallVectorImpl<Value *> &NewArgOperands) {7696          // When no alignment is specified for the load instruction,7697          // natural alignment is assumed.7698          createReplacementValues(7699              AlignAA ? AlignAA->getAssumedAlign() : Align(0),7700              *PrivatizableType, ACS,7701              ACS.getCallArgOperand(ARI.getReplacedArg().getArgNo()),7702              NewArgOperands);7703        };7704 7705    // Collect the types that will replace the privatizable type in the function7706    // signature.7707    SmallVector<Type *, 16> ReplacementTypes;7708    identifyReplacementTypes(*PrivatizableType, ReplacementTypes);7709 7710    // Register a rewrite of the argument.7711    if (A.registerFunctionSignatureRewrite(*Arg, ReplacementTypes,7712                                           std::move(FnRepairCB),7713                                           std::move(ACSRepairCB)))7714      return ChangeStatus::CHANGED;7715    return ChangeStatus::UNCHANGED;7716  }7717 7718  /// See AbstractAttribute::trackStatistics()7719  void trackStatistics() const override {7720    STATS_DECLTRACK_ARG_ATTR(privatizable_ptr);7721  }7722};7723 7724struct AAPrivatizablePtrFloating : public AAPrivatizablePtrImpl {7725  AAPrivatizablePtrFloating(const IRPosition &IRP, Attributor &A)7726      : AAPrivatizablePtrImpl(IRP, A) {}7727 7728  /// See AbstractAttribute::initialize(...).7729  void initialize(Attributor &A) override {7730    // TODO: We can privatize more than arguments.7731    indicatePessimisticFixpoint();7732  }7733 7734  ChangeStatus updateImpl(Attributor &A) override {7735    llvm_unreachable("AAPrivatizablePtr(Floating|Returned|CallSiteReturned)::"7736                     "updateImpl will not be called");7737  }7738 7739  /// See AAPrivatizablePtrImpl::identifyPrivatizableType(...)7740  std::optional<Type *> identifyPrivatizableType(Attributor &A) override {7741    Value *Obj = getUnderlyingObject(&getAssociatedValue());7742    if (!Obj) {7743      LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] No underlying object found!\n");7744      return nullptr;7745    }7746 7747    if (auto *AI = dyn_cast<AllocaInst>(Obj))7748      if (auto *CI = dyn_cast<ConstantInt>(AI->getArraySize()))7749        if (CI->isOne())7750          return AI->getAllocatedType();7751    if (auto *Arg = dyn_cast<Argument>(Obj)) {7752      auto *PrivArgAA = A.getAAFor<AAPrivatizablePtr>(7753          *this, IRPosition::argument(*Arg), DepClassTy::REQUIRED);7754      if (PrivArgAA && PrivArgAA->isAssumedPrivatizablePtr())7755        return PrivArgAA->getPrivatizableType();7756    }7757 7758    LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Underlying object neither valid "7759                         "alloca nor privatizable argument: "7760                      << *Obj << "!\n");7761    return nullptr;7762  }7763 7764  /// See AbstractAttribute::trackStatistics()7765  void trackStatistics() const override {7766    STATS_DECLTRACK_FLOATING_ATTR(privatizable_ptr);7767  }7768};7769 7770struct AAPrivatizablePtrCallSiteArgument final7771    : public AAPrivatizablePtrFloating {7772  AAPrivatizablePtrCallSiteArgument(const IRPosition &IRP, Attributor &A)7773      : AAPrivatizablePtrFloating(IRP, A) {}7774 7775  /// See AbstractAttribute::initialize(...).7776  void initialize(Attributor &A) override {7777    if (A.hasAttr(getIRPosition(), Attribute::ByVal))7778      indicateOptimisticFixpoint();7779  }7780 7781  /// See AbstractAttribute::updateImpl(...).7782  ChangeStatus updateImpl(Attributor &A) override {7783    PrivatizableType = identifyPrivatizableType(A);7784    if (!PrivatizableType)7785      return ChangeStatus::UNCHANGED;7786    if (!*PrivatizableType)7787      return indicatePessimisticFixpoint();7788 7789    const IRPosition &IRP = getIRPosition();7790    bool IsKnownNoCapture;7791    bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(7792        A, this, IRP, DepClassTy::REQUIRED, IsKnownNoCapture);7793    if (!IsAssumedNoCapture) {7794      LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer might be captured!\n");7795      return indicatePessimisticFixpoint();7796    }7797 7798    bool IsKnownNoAlias;7799    if (!AA::hasAssumedIRAttr<Attribute::NoAlias>(7800            A, this, IRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {7801      LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer might alias!\n");7802      return indicatePessimisticFixpoint();7803    }7804 7805    bool IsKnown;7806    if (!AA::isAssumedReadOnly(A, IRP, *this, IsKnown)) {7807      LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer is written!\n");7808      return indicatePessimisticFixpoint();7809    }7810 7811    return ChangeStatus::UNCHANGED;7812  }7813 7814  /// See AbstractAttribute::trackStatistics()7815  void trackStatistics() const override {7816    STATS_DECLTRACK_CSARG_ATTR(privatizable_ptr);7817  }7818};7819 7820struct AAPrivatizablePtrCallSiteReturned final7821    : public AAPrivatizablePtrFloating {7822  AAPrivatizablePtrCallSiteReturned(const IRPosition &IRP, Attributor &A)7823      : AAPrivatizablePtrFloating(IRP, A) {}7824 7825  /// See AbstractAttribute::initialize(...).7826  void initialize(Attributor &A) override {7827    // TODO: We can privatize more than arguments.7828    indicatePessimisticFixpoint();7829  }7830 7831  /// See AbstractAttribute::trackStatistics()7832  void trackStatistics() const override {7833    STATS_DECLTRACK_CSRET_ATTR(privatizable_ptr);7834  }7835};7836 7837struct AAPrivatizablePtrReturned final : public AAPrivatizablePtrFloating {7838  AAPrivatizablePtrReturned(const IRPosition &IRP, Attributor &A)7839      : AAPrivatizablePtrFloating(IRP, A) {}7840 7841  /// See AbstractAttribute::initialize(...).7842  void initialize(Attributor &A) override {7843    // TODO: We can privatize more than arguments.7844    indicatePessimisticFixpoint();7845  }7846 7847  /// See AbstractAttribute::trackStatistics()7848  void trackStatistics() const override {7849    STATS_DECLTRACK_FNRET_ATTR(privatizable_ptr);7850  }7851};7852} // namespace7853 7854/// -------------------- Memory Behavior Attributes ----------------------------7855/// Includes read-none, read-only, and write-only.7856/// ----------------------------------------------------------------------------7857namespace {7858struct AAMemoryBehaviorImpl : public AAMemoryBehavior {7859  AAMemoryBehaviorImpl(const IRPosition &IRP, Attributor &A)7860      : AAMemoryBehavior(IRP, A) {}7861 7862  /// See AbstractAttribute::initialize(...).7863  void initialize(Attributor &A) override {7864    intersectAssumedBits(BEST_STATE);7865    getKnownStateFromValue(A, getIRPosition(), getState());7866    AAMemoryBehavior::initialize(A);7867  }7868 7869  /// Return the memory behavior information encoded in the IR for \p IRP.7870  static void getKnownStateFromValue(Attributor &A, const IRPosition &IRP,7871                                     BitIntegerState &State,7872                                     bool IgnoreSubsumingPositions = false) {7873    SmallVector<Attribute, 2> Attrs;7874    A.getAttrs(IRP, AttrKinds, Attrs, IgnoreSubsumingPositions);7875    for (const Attribute &Attr : Attrs) {7876      switch (Attr.getKindAsEnum()) {7877      case Attribute::ReadNone:7878        State.addKnownBits(NO_ACCESSES);7879        break;7880      case Attribute::ReadOnly:7881        State.addKnownBits(NO_WRITES);7882        break;7883      case Attribute::WriteOnly:7884        State.addKnownBits(NO_READS);7885        break;7886      default:7887        llvm_unreachable("Unexpected attribute!");7888      }7889    }7890 7891    if (auto *I = dyn_cast<Instruction>(&IRP.getAnchorValue())) {7892      if (!I->mayReadFromMemory())7893        State.addKnownBits(NO_READS);7894      if (!I->mayWriteToMemory())7895        State.addKnownBits(NO_WRITES);7896    }7897  }7898 7899  /// See AbstractAttribute::getDeducedAttributes(...).7900  void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,7901                            SmallVectorImpl<Attribute> &Attrs) const override {7902    assert(Attrs.size() == 0);7903    if (isAssumedReadNone())7904      Attrs.push_back(Attribute::get(Ctx, Attribute::ReadNone));7905    else if (isAssumedReadOnly())7906      Attrs.push_back(Attribute::get(Ctx, Attribute::ReadOnly));7907    else if (isAssumedWriteOnly())7908      Attrs.push_back(Attribute::get(Ctx, Attribute::WriteOnly));7909    assert(Attrs.size() <= 1);7910  }7911 7912  /// See AbstractAttribute::manifest(...).7913  ChangeStatus manifest(Attributor &A) override {7914    const IRPosition &IRP = getIRPosition();7915 7916    if (A.hasAttr(IRP, Attribute::ReadNone,7917                  /* IgnoreSubsumingPositions */ true))7918      return ChangeStatus::UNCHANGED;7919 7920    // Check if we would improve the existing attributes first.7921    SmallVector<Attribute, 4> DeducedAttrs;7922    getDeducedAttributes(A, IRP.getAnchorValue().getContext(), DeducedAttrs);7923    if (llvm::all_of(DeducedAttrs, [&](const Attribute &Attr) {7924          return A.hasAttr(IRP, Attr.getKindAsEnum(),7925                           /* IgnoreSubsumingPositions */ true);7926        }))7927      return ChangeStatus::UNCHANGED;7928 7929    // Clear existing attributes.7930    A.removeAttrs(IRP, AttrKinds);7931    // Clear conflicting writable attribute.7932    if (isAssumedReadOnly())7933      A.removeAttrs(IRP, Attribute::Writable);7934 7935    // Use the generic manifest method.7936    return IRAttribute::manifest(A);7937  }7938 7939  /// See AbstractState::getAsStr().7940  const std::string getAsStr(Attributor *A) const override {7941    if (isAssumedReadNone())7942      return "readnone";7943    if (isAssumedReadOnly())7944      return "readonly";7945    if (isAssumedWriteOnly())7946      return "writeonly";7947    return "may-read/write";7948  }7949 7950  /// The set of IR attributes AAMemoryBehavior deals with.7951  static const Attribute::AttrKind AttrKinds[3];7952};7953 7954const Attribute::AttrKind AAMemoryBehaviorImpl::AttrKinds[] = {7955    Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly};7956 7957/// Memory behavior attribute for a floating value.7958struct AAMemoryBehaviorFloating : AAMemoryBehaviorImpl {7959  AAMemoryBehaviorFloating(const IRPosition &IRP, Attributor &A)7960      : AAMemoryBehaviorImpl(IRP, A) {}7961 7962  /// See AbstractAttribute::updateImpl(...).7963  ChangeStatus updateImpl(Attributor &A) override;7964 7965  /// See AbstractAttribute::trackStatistics()7966  void trackStatistics() const override {7967    if (isAssumedReadNone())7968      STATS_DECLTRACK_FLOATING_ATTR(readnone)7969    else if (isAssumedReadOnly())7970      STATS_DECLTRACK_FLOATING_ATTR(readonly)7971    else if (isAssumedWriteOnly())7972      STATS_DECLTRACK_FLOATING_ATTR(writeonly)7973  }7974 7975private:7976  /// Return true if users of \p UserI might access the underlying7977  /// variable/location described by \p U and should therefore be analyzed.7978  bool followUsersOfUseIn(Attributor &A, const Use &U,7979                          const Instruction *UserI);7980 7981  /// Update the state according to the effect of use \p U in \p UserI.7982  void analyzeUseIn(Attributor &A, const Use &U, const Instruction *UserI);7983};7984 7985/// Memory behavior attribute for function argument.7986struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating {7987  AAMemoryBehaviorArgument(const IRPosition &IRP, Attributor &A)7988      : AAMemoryBehaviorFloating(IRP, A) {}7989 7990  /// See AbstractAttribute::initialize(...).7991  void initialize(Attributor &A) override {7992    intersectAssumedBits(BEST_STATE);7993    const IRPosition &IRP = getIRPosition();7994    // TODO: Make IgnoreSubsumingPositions a property of an IRAttribute so we7995    // can query it when we use has/getAttr. That would allow us to reuse the7996    // initialize of the base class here.7997    bool HasByVal = A.hasAttr(IRP, {Attribute::ByVal},7998                              /* IgnoreSubsumingPositions */ true);7999    getKnownStateFromValue(A, IRP, getState(),8000                           /* IgnoreSubsumingPositions */ HasByVal);8001  }8002 8003  ChangeStatus manifest(Attributor &A) override {8004    // TODO: Pointer arguments are not supported on vectors of pointers yet.8005    if (!getAssociatedValue().getType()->isPointerTy())8006      return ChangeStatus::UNCHANGED;8007 8008    // TODO: From readattrs.ll: "inalloca parameters are always8009    //                           considered written"8010    if (A.hasAttr(getIRPosition(),8011                  {Attribute::InAlloca, Attribute::Preallocated})) {8012      removeKnownBits(NO_WRITES);8013      removeAssumedBits(NO_WRITES);8014    }8015    A.removeAttrs(getIRPosition(), AttrKinds);8016    return AAMemoryBehaviorFloating::manifest(A);8017  }8018 8019  /// See AbstractAttribute::trackStatistics()8020  void trackStatistics() const override {8021    if (isAssumedReadNone())8022      STATS_DECLTRACK_ARG_ATTR(readnone)8023    else if (isAssumedReadOnly())8024      STATS_DECLTRACK_ARG_ATTR(readonly)8025    else if (isAssumedWriteOnly())8026      STATS_DECLTRACK_ARG_ATTR(writeonly)8027  }8028};8029 8030struct AAMemoryBehaviorCallSiteArgument final : AAMemoryBehaviorArgument {8031  AAMemoryBehaviorCallSiteArgument(const IRPosition &IRP, Attributor &A)8032      : AAMemoryBehaviorArgument(IRP, A) {}8033 8034  /// See AbstractAttribute::initialize(...).8035  void initialize(Attributor &A) override {8036    // If we don't have an associated attribute this is either a variadic call8037    // or an indirect call, either way, nothing to do here.8038    Argument *Arg = getAssociatedArgument();8039    if (!Arg) {8040      indicatePessimisticFixpoint();8041      return;8042    }8043    if (Arg->hasByValAttr()) {8044      addKnownBits(NO_WRITES);8045      removeKnownBits(NO_READS);8046      removeAssumedBits(NO_READS);8047    }8048    AAMemoryBehaviorArgument::initialize(A);8049    if (getAssociatedFunction()->isDeclaration())8050      indicatePessimisticFixpoint();8051  }8052 8053  /// See AbstractAttribute::updateImpl(...).8054  ChangeStatus updateImpl(Attributor &A) override {8055    // TODO: Once we have call site specific value information we can provide8056    //       call site specific liveness liveness information and then it makes8057    //       sense to specialize attributes for call sites arguments instead of8058    //       redirecting requests to the callee argument.8059    Argument *Arg = getAssociatedArgument();8060    const IRPosition &ArgPos = IRPosition::argument(*Arg);8061    auto *ArgAA =8062        A.getAAFor<AAMemoryBehavior>(*this, ArgPos, DepClassTy::REQUIRED);8063    if (!ArgAA)8064      return indicatePessimisticFixpoint();8065    return clampStateAndIndicateChange(getState(), ArgAA->getState());8066  }8067 8068  /// See AbstractAttribute::trackStatistics()8069  void trackStatistics() const override {8070    if (isAssumedReadNone())8071      STATS_DECLTRACK_CSARG_ATTR(readnone)8072    else if (isAssumedReadOnly())8073      STATS_DECLTRACK_CSARG_ATTR(readonly)8074    else if (isAssumedWriteOnly())8075      STATS_DECLTRACK_CSARG_ATTR(writeonly)8076  }8077};8078 8079/// Memory behavior attribute for a call site return position.8080struct AAMemoryBehaviorCallSiteReturned final : AAMemoryBehaviorFloating {8081  AAMemoryBehaviorCallSiteReturned(const IRPosition &IRP, Attributor &A)8082      : AAMemoryBehaviorFloating(IRP, A) {}8083 8084  /// See AbstractAttribute::initialize(...).8085  void initialize(Attributor &A) override {8086    AAMemoryBehaviorImpl::initialize(A);8087  }8088  /// See AbstractAttribute::manifest(...).8089  ChangeStatus manifest(Attributor &A) override {8090    // We do not annotate returned values.8091    return ChangeStatus::UNCHANGED;8092  }8093 8094  /// See AbstractAttribute::trackStatistics()8095  void trackStatistics() const override {}8096};8097 8098/// An AA to represent the memory behavior function attributes.8099struct AAMemoryBehaviorFunction final : public AAMemoryBehaviorImpl {8100  AAMemoryBehaviorFunction(const IRPosition &IRP, Attributor &A)8101      : AAMemoryBehaviorImpl(IRP, A) {}8102 8103  /// See AbstractAttribute::updateImpl(Attributor &A).8104  ChangeStatus updateImpl(Attributor &A) override;8105 8106  /// See AbstractAttribute::manifest(...).8107  ChangeStatus manifest(Attributor &A) override {8108    // TODO: It would be better to merge this with AAMemoryLocation, so that8109    // we could determine read/write per location. This would also have the8110    // benefit of only one place trying to manifest the memory attribute.8111    Function &F = cast<Function>(getAnchorValue());8112    MemoryEffects ME = MemoryEffects::unknown();8113    if (isAssumedReadNone())8114      ME = MemoryEffects::none();8115    else if (isAssumedReadOnly())8116      ME = MemoryEffects::readOnly();8117    else if (isAssumedWriteOnly())8118      ME = MemoryEffects::writeOnly();8119 8120    A.removeAttrs(getIRPosition(), AttrKinds);8121    // Clear conflicting writable attribute.8122    if (ME.onlyReadsMemory())8123      for (Argument &Arg : F.args())8124        A.removeAttrs(IRPosition::argument(Arg), Attribute::Writable);8125    return A.manifestAttrs(getIRPosition(),8126                           Attribute::getWithMemoryEffects(F.getContext(), ME));8127  }8128 8129  /// See AbstractAttribute::trackStatistics()8130  void trackStatistics() const override {8131    if (isAssumedReadNone())8132      STATS_DECLTRACK_FN_ATTR(readnone)8133    else if (isAssumedReadOnly())8134      STATS_DECLTRACK_FN_ATTR(readonly)8135    else if (isAssumedWriteOnly())8136      STATS_DECLTRACK_FN_ATTR(writeonly)8137  }8138};8139 8140/// AAMemoryBehavior attribute for call sites.8141struct AAMemoryBehaviorCallSite final8142    : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl> {8143  AAMemoryBehaviorCallSite(const IRPosition &IRP, Attributor &A)8144      : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl>(IRP, A) {}8145 8146  /// See AbstractAttribute::manifest(...).8147  ChangeStatus manifest(Attributor &A) override {8148    // TODO: Deduplicate this with AAMemoryBehaviorFunction.8149    CallBase &CB = cast<CallBase>(getAnchorValue());8150    MemoryEffects ME = MemoryEffects::unknown();8151    if (isAssumedReadNone())8152      ME = MemoryEffects::none();8153    else if (isAssumedReadOnly())8154      ME = MemoryEffects::readOnly();8155    else if (isAssumedWriteOnly())8156      ME = MemoryEffects::writeOnly();8157 8158    A.removeAttrs(getIRPosition(), AttrKinds);8159    // Clear conflicting writable attribute.8160    if (ME.onlyReadsMemory())8161      for (Use &U : CB.args())8162        A.removeAttrs(IRPosition::callsite_argument(CB, U.getOperandNo()),8163                      Attribute::Writable);8164    return A.manifestAttrs(8165        getIRPosition(), Attribute::getWithMemoryEffects(CB.getContext(), ME));8166  }8167 8168  /// See AbstractAttribute::trackStatistics()8169  void trackStatistics() const override {8170    if (isAssumedReadNone())8171      STATS_DECLTRACK_CS_ATTR(readnone)8172    else if (isAssumedReadOnly())8173      STATS_DECLTRACK_CS_ATTR(readonly)8174    else if (isAssumedWriteOnly())8175      STATS_DECLTRACK_CS_ATTR(writeonly)8176  }8177};8178 8179ChangeStatus AAMemoryBehaviorFunction::updateImpl(Attributor &A) {8180 8181  // The current assumed state used to determine a change.8182  auto AssumedState = getAssumed();8183 8184  auto CheckRWInst = [&](Instruction &I) {8185    // If the instruction has an own memory behavior state, use it to restrict8186    // the local state. No further analysis is required as the other memory8187    // state is as optimistic as it gets.8188    if (const auto *CB = dyn_cast<CallBase>(&I)) {8189      const auto *MemBehaviorAA = A.getAAFor<AAMemoryBehavior>(8190          *this, IRPosition::callsite_function(*CB), DepClassTy::REQUIRED);8191      if (MemBehaviorAA) {8192        intersectAssumedBits(MemBehaviorAA->getAssumed());8193        return !isAtFixpoint();8194      }8195    }8196 8197    // Remove access kind modifiers if necessary.8198    if (I.mayReadFromMemory())8199      removeAssumedBits(NO_READS);8200    if (I.mayWriteToMemory())8201      removeAssumedBits(NO_WRITES);8202    return !isAtFixpoint();8203  };8204 8205  bool UsedAssumedInformation = false;8206  if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this,8207                                          UsedAssumedInformation))8208    return indicatePessimisticFixpoint();8209 8210  return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED8211                                        : ChangeStatus::UNCHANGED;8212}8213 8214ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &A) {8215 8216  const IRPosition &IRP = getIRPosition();8217  const IRPosition &FnPos = IRPosition::function_scope(IRP);8218  AAMemoryBehavior::StateType &S = getState();8219 8220  // First, check the function scope. We take the known information and we avoid8221  // work if the assumed information implies the current assumed information for8222  // this attribute. This is a valid for all but byval arguments.8223  Argument *Arg = IRP.getAssociatedArgument();8224  AAMemoryBehavior::base_t FnMemAssumedState =8225      AAMemoryBehavior::StateType::getWorstState();8226  if (!Arg || !Arg->hasByValAttr()) {8227    const auto *FnMemAA =8228        A.getAAFor<AAMemoryBehavior>(*this, FnPos, DepClassTy::OPTIONAL);8229    if (FnMemAA) {8230      FnMemAssumedState = FnMemAA->getAssumed();8231      S.addKnownBits(FnMemAA->getKnown());8232      if ((S.getAssumed() & FnMemAA->getAssumed()) == S.getAssumed())8233        return ChangeStatus::UNCHANGED;8234    }8235  }8236 8237  // The current assumed state used to determine a change.8238  auto AssumedState = S.getAssumed();8239 8240  // Make sure the value is not captured (except through "return"), if8241  // it is, any information derived would be irrelevant anyway as we cannot8242  // check the potential aliases introduced by the capture. However, no need8243  // to fall back to anythign less optimistic than the function state.8244  bool IsKnownNoCapture;8245  const AANoCapture *ArgNoCaptureAA = nullptr;8246  bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(8247      A, this, IRP, DepClassTy::OPTIONAL, IsKnownNoCapture, false,8248      &ArgNoCaptureAA);8249 8250  if (!IsAssumedNoCapture &&8251      (!ArgNoCaptureAA || !ArgNoCaptureAA->isAssumedNoCaptureMaybeReturned())) {8252    S.intersectAssumedBits(FnMemAssumedState);8253    return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED8254                                          : ChangeStatus::UNCHANGED;8255  }8256 8257  // Visit and expand uses until all are analyzed or a fixpoint is reached.8258  auto UsePred = [&](const Use &U, bool &Follow) -> bool {8259    Instruction *UserI = cast<Instruction>(U.getUser());8260    LLVM_DEBUG(dbgs() << "[AAMemoryBehavior] Use: " << *U << " in " << *UserI8261                      << " \n");8262 8263    // Droppable users, e.g., llvm::assume does not actually perform any action.8264    if (UserI->isDroppable())8265      return true;8266 8267    // Check if the users of UserI should also be visited.8268    Follow = followUsersOfUseIn(A, U, UserI);8269 8270    // If UserI might touch memory we analyze the use in detail.8271    if (UserI->mayReadOrWriteMemory())8272      analyzeUseIn(A, U, UserI);8273 8274    return !isAtFixpoint();8275  };8276 8277  if (!A.checkForAllUses(UsePred, *this, getAssociatedValue()))8278    return indicatePessimisticFixpoint();8279 8280  return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED8281                                        : ChangeStatus::UNCHANGED;8282}8283 8284bool AAMemoryBehaviorFloating::followUsersOfUseIn(Attributor &A, const Use &U,8285                                                  const Instruction *UserI) {8286  // The loaded value is unrelated to the pointer argument, no need to8287  // follow the users of the load.8288  if (isa<LoadInst>(UserI) || isa<ReturnInst>(UserI))8289    return false;8290 8291  // By default we follow all uses assuming UserI might leak information on U,8292  // we have special handling for call sites operands though.8293  const auto *CB = dyn_cast<CallBase>(UserI);8294  if (!CB || !CB->isArgOperand(&U))8295    return true;8296 8297  // If the use is a call argument known not to be captured, the users of8298  // the call do not need to be visited because they have to be unrelated to8299  // the input. Note that this check is not trivial even though we disallow8300  // general capturing of the underlying argument. The reason is that the8301  // call might the argument "through return", which we allow and for which we8302  // need to check call users.8303  if (U.get()->getType()->isPointerTy()) {8304    unsigned ArgNo = CB->getArgOperandNo(&U);8305    bool IsKnownNoCapture;8306    return !AA::hasAssumedIRAttr<Attribute::Captures>(8307        A, this, IRPosition::callsite_argument(*CB, ArgNo),8308        DepClassTy::OPTIONAL, IsKnownNoCapture);8309  }8310 8311  return true;8312}8313 8314void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &A, const Use &U,8315                                            const Instruction *UserI) {8316  assert(UserI->mayReadOrWriteMemory());8317 8318  switch (UserI->getOpcode()) {8319  default:8320    // TODO: Handle all atomics and other side-effect operations we know of.8321    break;8322  case Instruction::Load:8323    // Loads cause the NO_READS property to disappear.8324    removeAssumedBits(NO_READS);8325    return;8326 8327  case Instruction::Store:8328    // Stores cause the NO_WRITES property to disappear if the use is the8329    // pointer operand. Note that while capturing was taken care of somewhere8330    // else we need to deal with stores of the value that is not looked through.8331    if (cast<StoreInst>(UserI)->getPointerOperand() == U.get())8332      removeAssumedBits(NO_WRITES);8333    else8334      indicatePessimisticFixpoint();8335    return;8336 8337  case Instruction::Call:8338  case Instruction::CallBr:8339  case Instruction::Invoke: {8340    // For call sites we look at the argument memory behavior attribute (this8341    // could be recursive!) in order to restrict our own state.8342    const auto *CB = cast<CallBase>(UserI);8343 8344    // Give up on operand bundles.8345    if (CB->isBundleOperand(&U)) {8346      indicatePessimisticFixpoint();8347      return;8348    }8349 8350    // Calling a function does read the function pointer, maybe write it if the8351    // function is self-modifying.8352    if (CB->isCallee(&U)) {8353      removeAssumedBits(NO_READS);8354      break;8355    }8356 8357    // Adjust the possible access behavior based on the information on the8358    // argument.8359    IRPosition Pos;8360    if (U.get()->getType()->isPointerTy())8361      Pos = IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U));8362    else8363      Pos = IRPosition::callsite_function(*CB);8364    const auto *MemBehaviorAA =8365        A.getAAFor<AAMemoryBehavior>(*this, Pos, DepClassTy::OPTIONAL);8366    if (!MemBehaviorAA)8367      break;8368    // "assumed" has at most the same bits as the MemBehaviorAA assumed8369    // and at least "known".8370    intersectAssumedBits(MemBehaviorAA->getAssumed());8371    return;8372  }8373  };8374 8375  // Generally, look at the "may-properties" and adjust the assumed state if we8376  // did not trigger special handling before.8377  if (UserI->mayReadFromMemory())8378    removeAssumedBits(NO_READS);8379  if (UserI->mayWriteToMemory())8380    removeAssumedBits(NO_WRITES);8381}8382} // namespace8383 8384/// -------------------- Memory Locations Attributes ---------------------------8385/// Includes read-none, argmemonly, inaccessiblememonly,8386/// inaccessiblememorargmemonly8387/// ----------------------------------------------------------------------------8388 8389std::string AAMemoryLocation::getMemoryLocationsAsStr(8390    AAMemoryLocation::MemoryLocationsKind MLK) {8391  if (0 == (MLK & AAMemoryLocation::NO_LOCATIONS))8392    return "all memory";8393  if (MLK == AAMemoryLocation::NO_LOCATIONS)8394    return "no memory";8395  std::string S = "memory:";8396  if (0 == (MLK & AAMemoryLocation::NO_LOCAL_MEM))8397    S += "stack,";8398  if (0 == (MLK & AAMemoryLocation::NO_CONST_MEM))8399    S += "constant,";8400  if (0 == (MLK & AAMemoryLocation::NO_GLOBAL_INTERNAL_MEM))8401    S += "internal global,";8402  if (0 == (MLK & AAMemoryLocation::NO_GLOBAL_EXTERNAL_MEM))8403    S += "external global,";8404  if (0 == (MLK & AAMemoryLocation::NO_ARGUMENT_MEM))8405    S += "argument,";8406  if (0 == (MLK & AAMemoryLocation::NO_INACCESSIBLE_MEM))8407    S += "inaccessible,";8408  if (0 == (MLK & AAMemoryLocation::NO_MALLOCED_MEM))8409    S += "malloced,";8410  if (0 == (MLK & AAMemoryLocation::NO_UNKOWN_MEM))8411    S += "unknown,";8412  S.pop_back();8413  return S;8414}8415 8416namespace {8417struct AAMemoryLocationImpl : public AAMemoryLocation {8418 8419  AAMemoryLocationImpl(const IRPosition &IRP, Attributor &A)8420      : AAMemoryLocation(IRP, A), Allocator(A.Allocator) {8421    AccessKind2Accesses.fill(nullptr);8422  }8423 8424  ~AAMemoryLocationImpl() override {8425    // The AccessSets are allocated via a BumpPtrAllocator, we call8426    // the destructor manually.8427    for (AccessSet *AS : AccessKind2Accesses)8428      if (AS)8429        AS->~AccessSet();8430  }8431 8432  /// See AbstractAttribute::initialize(...).8433  void initialize(Attributor &A) override {8434    intersectAssumedBits(BEST_STATE);8435    getKnownStateFromValue(A, getIRPosition(), getState());8436    AAMemoryLocation::initialize(A);8437  }8438 8439  /// Return the memory behavior information encoded in the IR for \p IRP.8440  static void getKnownStateFromValue(Attributor &A, const IRPosition &IRP,8441                                     BitIntegerState &State,8442                                     bool IgnoreSubsumingPositions = false) {8443    // For internal functions we ignore `argmemonly` and8444    // `inaccessiblememorargmemonly` as we might break it via interprocedural8445    // constant propagation. It is unclear if this is the best way but it is8446    // unlikely this will cause real performance problems. If we are deriving8447    // attributes for the anchor function we even remove the attribute in8448    // addition to ignoring it.8449    // TODO: A better way to handle this would be to add ~NO_GLOBAL_MEM /8450    // MemoryEffects::Other as a possible location.8451    bool UseArgMemOnly = true;8452    Function *AnchorFn = IRP.getAnchorScope();8453    if (AnchorFn && A.isRunOn(*AnchorFn))8454      UseArgMemOnly = !AnchorFn->hasLocalLinkage();8455 8456    SmallVector<Attribute, 2> Attrs;8457    A.getAttrs(IRP, {Attribute::Memory}, Attrs, IgnoreSubsumingPositions);8458    for (const Attribute &Attr : Attrs) {8459      // TODO: We can map MemoryEffects to Attributor locations more precisely.8460      MemoryEffects ME = Attr.getMemoryEffects();8461      if (ME.doesNotAccessMemory()) {8462        State.addKnownBits(NO_LOCAL_MEM | NO_CONST_MEM);8463        continue;8464      }8465      if (ME.onlyAccessesInaccessibleMem()) {8466        State.addKnownBits(inverseLocation(NO_INACCESSIBLE_MEM, true, true));8467        continue;8468      }8469      if (ME.onlyAccessesArgPointees()) {8470        if (UseArgMemOnly)8471          State.addKnownBits(inverseLocation(NO_ARGUMENT_MEM, true, true));8472        else {8473          // Remove location information, only keep read/write info.8474          ME = MemoryEffects(ME.getModRef());8475          A.manifestAttrs(IRP,8476                          Attribute::getWithMemoryEffects(8477                              IRP.getAnchorValue().getContext(), ME),8478                          /*ForceReplace*/ true);8479        }8480        continue;8481      }8482      if (ME.onlyAccessesInaccessibleOrArgMem()) {8483        if (UseArgMemOnly)8484          State.addKnownBits(inverseLocation(8485              NO_INACCESSIBLE_MEM | NO_ARGUMENT_MEM, true, true));8486        else {8487          // Remove location information, only keep read/write info.8488          ME = MemoryEffects(ME.getModRef());8489          A.manifestAttrs(IRP,8490                          Attribute::getWithMemoryEffects(8491                              IRP.getAnchorValue().getContext(), ME),8492                          /*ForceReplace*/ true);8493        }8494        continue;8495      }8496    }8497  }8498 8499  /// See AbstractAttribute::getDeducedAttributes(...).8500  void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,8501                            SmallVectorImpl<Attribute> &Attrs) const override {8502    // TODO: We can map Attributor locations to MemoryEffects more precisely.8503    assert(Attrs.size() == 0);8504    if (getIRPosition().getPositionKind() == IRPosition::IRP_FUNCTION) {8505      if (isAssumedReadNone())8506        Attrs.push_back(8507            Attribute::getWithMemoryEffects(Ctx, MemoryEffects::none()));8508      else if (isAssumedInaccessibleMemOnly())8509        Attrs.push_back(Attribute::getWithMemoryEffects(8510            Ctx, MemoryEffects::inaccessibleMemOnly()));8511      else if (isAssumedArgMemOnly())8512        Attrs.push_back(8513            Attribute::getWithMemoryEffects(Ctx, MemoryEffects::argMemOnly()));8514      else if (isAssumedInaccessibleOrArgMemOnly())8515        Attrs.push_back(Attribute::getWithMemoryEffects(8516            Ctx, MemoryEffects::inaccessibleOrArgMemOnly()));8517    }8518    assert(Attrs.size() <= 1);8519  }8520 8521  /// See AbstractAttribute::manifest(...).8522  ChangeStatus manifest(Attributor &A) override {8523    // TODO: If AAMemoryLocation and AAMemoryBehavior are merged, we could8524    // provide per-location modref information here.8525    const IRPosition &IRP = getIRPosition();8526 8527    SmallVector<Attribute, 1> DeducedAttrs;8528    getDeducedAttributes(A, IRP.getAnchorValue().getContext(), DeducedAttrs);8529    if (DeducedAttrs.size() != 1)8530      return ChangeStatus::UNCHANGED;8531    MemoryEffects ME = DeducedAttrs[0].getMemoryEffects();8532 8533    return A.manifestAttrs(IRP, Attribute::getWithMemoryEffects(8534                                    IRP.getAnchorValue().getContext(), ME));8535  }8536 8537  /// See AAMemoryLocation::checkForAllAccessesToMemoryKind(...).8538  bool checkForAllAccessesToMemoryKind(8539      function_ref<bool(const Instruction *, const Value *, AccessKind,8540                        MemoryLocationsKind)>8541          Pred,8542      MemoryLocationsKind RequestedMLK) const override {8543    if (!isValidState())8544      return false;8545 8546    MemoryLocationsKind AssumedMLK = getAssumedNotAccessedLocation();8547    if (AssumedMLK == NO_LOCATIONS)8548      return true;8549 8550    unsigned Idx = 0;8551    for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS;8552         CurMLK *= 2, ++Idx) {8553      if (CurMLK & RequestedMLK)8554        continue;8555 8556      if (const AccessSet *Accesses = AccessKind2Accesses[Idx])8557        for (const AccessInfo &AI : *Accesses)8558          if (!Pred(AI.I, AI.Ptr, AI.Kind, CurMLK))8559            return false;8560    }8561 8562    return true;8563  }8564 8565  ChangeStatus indicatePessimisticFixpoint() override {8566    // If we give up and indicate a pessimistic fixpoint this instruction will8567    // become an access for all potential access kinds:8568    // TODO: Add pointers for argmemonly and globals to improve the results of8569    //       checkForAllAccessesToMemoryKind.8570    bool Changed = false;8571    MemoryLocationsKind KnownMLK = getKnown();8572    Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());8573    for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2)8574      if (!(CurMLK & KnownMLK))8575        updateStateAndAccessesMap(getState(), CurMLK, I, nullptr, Changed,8576                                  getAccessKindFromInst(I));8577    return AAMemoryLocation::indicatePessimisticFixpoint();8578  }8579 8580protected:8581  /// Helper struct to tie together an instruction that has a read or write8582  /// effect with the pointer it accesses (if any).8583  struct AccessInfo {8584 8585    /// The instruction that caused the access.8586    const Instruction *I;8587 8588    /// The base pointer that is accessed, or null if unknown.8589    const Value *Ptr;8590 8591    /// The kind of access (read/write/read+write).8592    AccessKind Kind;8593 8594    bool operator==(const AccessInfo &RHS) const {8595      return I == RHS.I && Ptr == RHS.Ptr && Kind == RHS.Kind;8596    }8597    bool operator()(const AccessInfo &LHS, const AccessInfo &RHS) const {8598      if (LHS.I != RHS.I)8599        return LHS.I < RHS.I;8600      if (LHS.Ptr != RHS.Ptr)8601        return LHS.Ptr < RHS.Ptr;8602      if (LHS.Kind != RHS.Kind)8603        return LHS.Kind < RHS.Kind;8604      return false;8605    }8606  };8607 8608  /// Mapping from *single* memory location kinds, e.g., LOCAL_MEM with the8609  /// value of NO_LOCAL_MEM, to the accesses encountered for this memory kind.8610  using AccessSet = SmallSet<AccessInfo, 2, AccessInfo>;8611  std::array<AccessSet *, llvm::ConstantLog2<VALID_STATE>()>8612      AccessKind2Accesses;8613 8614  /// Categorize the pointer arguments of CB that might access memory in8615  /// AccessedLoc and update the state and access map accordingly.8616  void8617  categorizeArgumentPointerLocations(Attributor &A, CallBase &CB,8618                                     AAMemoryLocation::StateType &AccessedLocs,8619                                     bool &Changed);8620 8621  /// Return the kind(s) of location that may be accessed by \p V.8622  AAMemoryLocation::MemoryLocationsKind8623  categorizeAccessedLocations(Attributor &A, Instruction &I, bool &Changed);8624 8625  /// Return the access kind as determined by \p I.8626  AccessKind getAccessKindFromInst(const Instruction *I) {8627    AccessKind AK = READ_WRITE;8628    if (I) {8629      AK = I->mayReadFromMemory() ? READ : NONE;8630      AK = AccessKind(AK | (I->mayWriteToMemory() ? WRITE : NONE));8631    }8632    return AK;8633  }8634 8635  /// Update the state \p State and the AccessKind2Accesses given that \p I is8636  /// an access of kind \p AK to a \p MLK memory location with the access8637  /// pointer \p Ptr.8638  void updateStateAndAccessesMap(AAMemoryLocation::StateType &State,8639                                 MemoryLocationsKind MLK, const Instruction *I,8640                                 const Value *Ptr, bool &Changed,8641                                 AccessKind AK = READ_WRITE) {8642 8643    assert(isPowerOf2_32(MLK) && "Expected a single location set!");8644    auto *&Accesses = AccessKind2Accesses[llvm::Log2_32(MLK)];8645    if (!Accesses)8646      Accesses = new (Allocator) AccessSet();8647    Changed |= Accesses->insert(AccessInfo{I, Ptr, AK}).second;8648    if (MLK == NO_UNKOWN_MEM)8649      MLK = NO_LOCATIONS;8650    State.removeAssumedBits(MLK);8651  }8652 8653  /// Determine the underlying locations kinds for \p Ptr, e.g., globals or8654  /// arguments, and update the state and access map accordingly.8655  void categorizePtrValue(Attributor &A, const Instruction &I, const Value &Ptr,8656                          AAMemoryLocation::StateType &State, bool &Changed,8657                          unsigned AccessAS = 0);8658 8659  /// Used to allocate access sets.8660  BumpPtrAllocator &Allocator;8661};8662 8663void AAMemoryLocationImpl::categorizePtrValue(8664    Attributor &A, const Instruction &I, const Value &Ptr,8665    AAMemoryLocation::StateType &State, bool &Changed, unsigned AccessAS) {8666  LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize pointer locations for "8667                    << Ptr << " ["8668                    << getMemoryLocationsAsStr(State.getAssumed()) << "]\n");8669 8670  auto Pred = [&](Value &Obj) {8671    unsigned ObjectAS = Obj.getType()->getPointerAddressSpace();8672    // TODO: recognize the TBAA used for constant accesses.8673    MemoryLocationsKind MLK = NO_LOCATIONS;8674 8675    // Filter accesses to constant (GPU) memory if we have an AS at the access8676    // site or the object is known to actually have the associated AS.8677    if ((AccessAS == (unsigned)AA::GPUAddressSpace::Constant ||8678         (ObjectAS == (unsigned)AA::GPUAddressSpace::Constant &&8679          isIdentifiedObject(&Obj))) &&8680        AA::isGPU(*I.getModule()))8681      return true;8682 8683    if (isa<UndefValue>(&Obj))8684      return true;8685    if (isa<Argument>(&Obj)) {8686      // TODO: For now we do not treat byval arguments as local copies performed8687      // on the call edge, though, we should. To make that happen we need to8688      // teach various passes, e.g., DSE, about the copy effect of a byval. That8689      // would also allow us to mark functions only accessing byval arguments as8690      // readnone again, arguably their accesses have no effect outside of the8691      // function, like accesses to allocas.8692      MLK = NO_ARGUMENT_MEM;8693    } else if (auto *GV = dyn_cast<GlobalValue>(&Obj)) {8694      // Reading constant memory is not treated as a read "effect" by the8695      // function attr pass so we won't neither. Constants defined by TBAA are8696      // similar. (We know we do not write it because it is constant.)8697      if (auto *GVar = dyn_cast<GlobalVariable>(GV))8698        if (GVar->isConstant())8699          return true;8700 8701      if (GV->hasLocalLinkage())8702        MLK = NO_GLOBAL_INTERNAL_MEM;8703      else8704        MLK = NO_GLOBAL_EXTERNAL_MEM;8705    } else if (isa<ConstantPointerNull>(&Obj) &&8706               (!NullPointerIsDefined(getAssociatedFunction(), AccessAS) ||8707                !NullPointerIsDefined(getAssociatedFunction(), ObjectAS))) {8708      return true;8709    } else if (isa<AllocaInst>(&Obj)) {8710      MLK = NO_LOCAL_MEM;8711    } else if (const auto *CB = dyn_cast<CallBase>(&Obj)) {8712      bool IsKnownNoAlias;8713      if (AA::hasAssumedIRAttr<Attribute::NoAlias>(8714              A, this, IRPosition::callsite_returned(*CB), DepClassTy::OPTIONAL,8715              IsKnownNoAlias))8716        MLK = NO_MALLOCED_MEM;8717      else8718        MLK = NO_UNKOWN_MEM;8719    } else {8720      MLK = NO_UNKOWN_MEM;8721    }8722 8723    assert(MLK != NO_LOCATIONS && "No location specified!");8724    LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Ptr value can be categorized: "8725                      << Obj << " -> " << getMemoryLocationsAsStr(MLK) << "\n");8726    updateStateAndAccessesMap(State, MLK, &I, &Obj, Changed,8727                              getAccessKindFromInst(&I));8728 8729    return true;8730  };8731 8732  const auto *AA = A.getAAFor<AAUnderlyingObjects>(8733      *this, IRPosition::value(Ptr), DepClassTy::OPTIONAL);8734  if (!AA || !AA->forallUnderlyingObjects(Pred, AA::Intraprocedural)) {8735    LLVM_DEBUG(8736        dbgs() << "[AAMemoryLocation] Pointer locations not categorized\n");8737    updateStateAndAccessesMap(State, NO_UNKOWN_MEM, &I, nullptr, Changed,8738                              getAccessKindFromInst(&I));8739    return;8740  }8741 8742  LLVM_DEBUG(8743      dbgs() << "[AAMemoryLocation] Accessed locations with pointer locations: "8744             << getMemoryLocationsAsStr(State.getAssumed()) << "\n");8745}8746 8747void AAMemoryLocationImpl::categorizeArgumentPointerLocations(8748    Attributor &A, CallBase &CB, AAMemoryLocation::StateType &AccessedLocs,8749    bool &Changed) {8750  for (unsigned ArgNo = 0, E = CB.arg_size(); ArgNo < E; ++ArgNo) {8751 8752    // Skip non-pointer arguments.8753    const Value *ArgOp = CB.getArgOperand(ArgNo);8754    if (!ArgOp->getType()->isPtrOrPtrVectorTy())8755      continue;8756 8757    // Skip readnone arguments.8758    const IRPosition &ArgOpIRP = IRPosition::callsite_argument(CB, ArgNo);8759    const auto *ArgOpMemLocationAA =8760        A.getAAFor<AAMemoryBehavior>(*this, ArgOpIRP, DepClassTy::OPTIONAL);8761 8762    if (ArgOpMemLocationAA && ArgOpMemLocationAA->isAssumedReadNone())8763      continue;8764 8765    // Categorize potentially accessed pointer arguments as if there was an8766    // access instruction with them as pointer.8767    categorizePtrValue(A, CB, *ArgOp, AccessedLocs, Changed);8768  }8769}8770 8771AAMemoryLocation::MemoryLocationsKind8772AAMemoryLocationImpl::categorizeAccessedLocations(Attributor &A, Instruction &I,8773                                                  bool &Changed) {8774  LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize accessed locations for "8775                    << I << "\n");8776 8777  AAMemoryLocation::StateType AccessedLocs;8778  AccessedLocs.intersectAssumedBits(NO_LOCATIONS);8779 8780  if (auto *CB = dyn_cast<CallBase>(&I)) {8781 8782    // First check if we assume any memory is access is visible.8783    const auto *CBMemLocationAA = A.getAAFor<AAMemoryLocation>(8784        *this, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL);8785    LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize call site: " << I8786                      << " [" << CBMemLocationAA << "]\n");8787    if (!CBMemLocationAA) {8788      updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &I, nullptr,8789                                Changed, getAccessKindFromInst(&I));8790      return NO_UNKOWN_MEM;8791    }8792 8793    if (CBMemLocationAA->isAssumedReadNone())8794      return NO_LOCATIONS;8795 8796    if (CBMemLocationAA->isAssumedInaccessibleMemOnly()) {8797      updateStateAndAccessesMap(AccessedLocs, NO_INACCESSIBLE_MEM, &I, nullptr,8798                                Changed, getAccessKindFromInst(&I));8799      return AccessedLocs.getAssumed();8800    }8801 8802    uint32_t CBAssumedNotAccessedLocs =8803        CBMemLocationAA->getAssumedNotAccessedLocation();8804 8805    // Set the argmemonly and global bit as we handle them separately below.8806    uint32_t CBAssumedNotAccessedLocsNoArgMem =8807        CBAssumedNotAccessedLocs | NO_ARGUMENT_MEM | NO_GLOBAL_MEM;8808 8809    for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2) {8810      if (CBAssumedNotAccessedLocsNoArgMem & CurMLK)8811        continue;8812      updateStateAndAccessesMap(AccessedLocs, CurMLK, &I, nullptr, Changed,8813                                getAccessKindFromInst(&I));8814    }8815 8816    // Now handle global memory if it might be accessed. This is slightly tricky8817    // as NO_GLOBAL_MEM has multiple bits set.8818    bool HasGlobalAccesses = ((~CBAssumedNotAccessedLocs) & NO_GLOBAL_MEM);8819    if (HasGlobalAccesses) {8820      auto AccessPred = [&](const Instruction *, const Value *Ptr,8821                            AccessKind Kind, MemoryLocationsKind MLK) {8822        updateStateAndAccessesMap(AccessedLocs, MLK, &I, Ptr, Changed,8823                                  getAccessKindFromInst(&I));8824        return true;8825      };8826      if (!CBMemLocationAA->checkForAllAccessesToMemoryKind(8827              AccessPred, inverseLocation(NO_GLOBAL_MEM, false, false)))8828        return AccessedLocs.getWorstState();8829    }8830 8831    LLVM_DEBUG(8832        dbgs() << "[AAMemoryLocation] Accessed state before argument handling: "8833               << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) << "\n");8834 8835    // Now handle argument memory if it might be accessed.8836    bool HasArgAccesses = ((~CBAssumedNotAccessedLocs) & NO_ARGUMENT_MEM);8837    if (HasArgAccesses)8838      categorizeArgumentPointerLocations(A, *CB, AccessedLocs, Changed);8839 8840    LLVM_DEBUG(8841        dbgs() << "[AAMemoryLocation] Accessed state after argument handling: "8842               << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) << "\n");8843 8844    return AccessedLocs.getAssumed();8845  }8846 8847  if (const Value *Ptr = getPointerOperand(&I, /* AllowVolatile */ true)) {8848    LLVM_DEBUG(8849        dbgs() << "[AAMemoryLocation] Categorize memory access with pointer: "8850               << I << " [" << *Ptr << "]\n");8851    categorizePtrValue(A, I, *Ptr, AccessedLocs, Changed,8852                       Ptr->getType()->getPointerAddressSpace());8853    return AccessedLocs.getAssumed();8854  }8855 8856  LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Failed to categorize instruction: "8857                    << I << "\n");8858  updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &I, nullptr, Changed,8859                            getAccessKindFromInst(&I));8860  return AccessedLocs.getAssumed();8861}8862 8863/// An AA to represent the memory behavior function attributes.8864struct AAMemoryLocationFunction final : public AAMemoryLocationImpl {8865  AAMemoryLocationFunction(const IRPosition &IRP, Attributor &A)8866      : AAMemoryLocationImpl(IRP, A) {}8867 8868  /// See AbstractAttribute::updateImpl(Attributor &A).8869  ChangeStatus updateImpl(Attributor &A) override {8870 8871    const auto *MemBehaviorAA =8872        A.getAAFor<AAMemoryBehavior>(*this, getIRPosition(), DepClassTy::NONE);8873    if (MemBehaviorAA && MemBehaviorAA->isAssumedReadNone()) {8874      if (MemBehaviorAA->isKnownReadNone())8875        return indicateOptimisticFixpoint();8876      assert(isAssumedReadNone() &&8877             "AAMemoryLocation was not read-none but AAMemoryBehavior was!");8878      A.recordDependence(*MemBehaviorAA, *this, DepClassTy::OPTIONAL);8879      return ChangeStatus::UNCHANGED;8880    }8881 8882    // The current assumed state used to determine a change.8883    auto AssumedState = getAssumed();8884    bool Changed = false;8885 8886    auto CheckRWInst = [&](Instruction &I) {8887      MemoryLocationsKind MLK = categorizeAccessedLocations(A, I, Changed);8888      LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Accessed locations for " << I8889                        << ": " << getMemoryLocationsAsStr(MLK) << "\n");8890      removeAssumedBits(inverseLocation(MLK, false, false));8891      // Stop once only the valid bit set in the *not assumed location*, thus8892      // once we don't actually exclude any memory locations in the state.8893      return getAssumedNotAccessedLocation() != VALID_STATE;8894    };8895 8896    bool UsedAssumedInformation = false;8897    if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this,8898                                            UsedAssumedInformation))8899      return indicatePessimisticFixpoint();8900 8901    Changed |= AssumedState != getAssumed();8902    return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;8903  }8904 8905  /// See AbstractAttribute::trackStatistics()8906  void trackStatistics() const override {8907    if (isAssumedReadNone())8908      STATS_DECLTRACK_FN_ATTR(readnone)8909    else if (isAssumedArgMemOnly())8910      STATS_DECLTRACK_FN_ATTR(argmemonly)8911    else if (isAssumedInaccessibleMemOnly())8912      STATS_DECLTRACK_FN_ATTR(inaccessiblememonly)8913    else if (isAssumedInaccessibleOrArgMemOnly())8914      STATS_DECLTRACK_FN_ATTR(inaccessiblememorargmemonly)8915  }8916};8917 8918/// AAMemoryLocation attribute for call sites.8919struct AAMemoryLocationCallSite final : AAMemoryLocationImpl {8920  AAMemoryLocationCallSite(const IRPosition &IRP, Attributor &A)8921      : AAMemoryLocationImpl(IRP, A) {}8922 8923  /// See AbstractAttribute::updateImpl(...).8924  ChangeStatus updateImpl(Attributor &A) override {8925    // TODO: Once we have call site specific value information we can provide8926    //       call site specific liveness liveness information and then it makes8927    //       sense to specialize attributes for call sites arguments instead of8928    //       redirecting requests to the callee argument.8929    Function *F = getAssociatedFunction();8930    const IRPosition &FnPos = IRPosition::function(*F);8931    auto *FnAA =8932        A.getAAFor<AAMemoryLocation>(*this, FnPos, DepClassTy::REQUIRED);8933    if (!FnAA)8934      return indicatePessimisticFixpoint();8935    bool Changed = false;8936    auto AccessPred = [&](const Instruction *I, const Value *Ptr,8937                          AccessKind Kind, MemoryLocationsKind MLK) {8938      updateStateAndAccessesMap(getState(), MLK, I, Ptr, Changed,8939                                getAccessKindFromInst(I));8940      return true;8941    };8942    if (!FnAA->checkForAllAccessesToMemoryKind(AccessPred, ALL_LOCATIONS))8943      return indicatePessimisticFixpoint();8944    return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;8945  }8946 8947  /// See AbstractAttribute::trackStatistics()8948  void trackStatistics() const override {8949    if (isAssumedReadNone())8950      STATS_DECLTRACK_CS_ATTR(readnone)8951  }8952};8953} // namespace8954 8955/// ------------------ denormal-fp-math Attribute -------------------------8956 8957namespace {8958struct AADenormalFPMathImpl : public AADenormalFPMath {8959  AADenormalFPMathImpl(const IRPosition &IRP, Attributor &A)8960      : AADenormalFPMath(IRP, A) {}8961 8962  const std::string getAsStr(Attributor *A) const override {8963    std::string Str("AADenormalFPMath[");8964    raw_string_ostream OS(Str);8965 8966    DenormalState Known = getKnown();8967    if (Known.Mode.isValid())8968      OS << "denormal-fp-math=" << Known.Mode;8969    else8970      OS << "invalid";8971 8972    if (Known.ModeF32.isValid())8973      OS << " denormal-fp-math-f32=" << Known.ModeF32;8974    OS << ']';8975    return Str;8976  }8977};8978 8979struct AADenormalFPMathFunction final : AADenormalFPMathImpl {8980  AADenormalFPMathFunction(const IRPosition &IRP, Attributor &A)8981      : AADenormalFPMathImpl(IRP, A) {}8982 8983  void initialize(Attributor &A) override {8984    const Function *F = getAnchorScope();8985    DenormalMode Mode = F->getDenormalModeRaw();8986    DenormalMode ModeF32 = F->getDenormalModeF32Raw();8987 8988    // TODO: Handling this here prevents handling the case where a callee has a8989    // fixed denormal-fp-math with dynamic denormal-fp-math-f32, but called from8990    // a function with a fully fixed mode.8991    if (ModeF32 == DenormalMode::getInvalid())8992      ModeF32 = Mode;8993    Known = DenormalState{Mode, ModeF32};8994    if (isModeFixed())8995      indicateFixpoint();8996  }8997 8998  ChangeStatus updateImpl(Attributor &A) override {8999    ChangeStatus Change = ChangeStatus::UNCHANGED;9000 9001    auto CheckCallSite = [=, &Change, &A](AbstractCallSite CS) {9002      Function *Caller = CS.getInstruction()->getFunction();9003      LLVM_DEBUG(dbgs() << "[AADenormalFPMath] Call " << Caller->getName()9004                        << "->" << getAssociatedFunction()->getName() << '\n');9005 9006      const auto *CallerInfo = A.getAAFor<AADenormalFPMath>(9007          *this, IRPosition::function(*Caller), DepClassTy::REQUIRED);9008      if (!CallerInfo)9009        return false;9010 9011      Change = Change | clampStateAndIndicateChange(this->getState(),9012                                                    CallerInfo->getState());9013      return true;9014    };9015 9016    bool AllCallSitesKnown = true;9017    if (!A.checkForAllCallSites(CheckCallSite, *this, true, AllCallSitesKnown))9018      return indicatePessimisticFixpoint();9019 9020    if (Change == ChangeStatus::CHANGED && isModeFixed())9021      indicateFixpoint();9022    return Change;9023  }9024 9025  ChangeStatus manifest(Attributor &A) override {9026    LLVMContext &Ctx = getAssociatedFunction()->getContext();9027 9028    SmallVector<Attribute, 2> AttrToAdd;9029    SmallVector<StringRef, 2> AttrToRemove;9030    if (Known.Mode == DenormalMode::getDefault()) {9031      AttrToRemove.push_back("denormal-fp-math");9032    } else {9033      AttrToAdd.push_back(9034          Attribute::get(Ctx, "denormal-fp-math", Known.Mode.str()));9035    }9036 9037    if (Known.ModeF32 != Known.Mode) {9038      AttrToAdd.push_back(9039          Attribute::get(Ctx, "denormal-fp-math-f32", Known.ModeF32.str()));9040    } else {9041      AttrToRemove.push_back("denormal-fp-math-f32");9042    }9043 9044    auto &IRP = getIRPosition();9045 9046    // TODO: There should be a combined add and remove API.9047    return A.removeAttrs(IRP, AttrToRemove) |9048           A.manifestAttrs(IRP, AttrToAdd, /*ForceReplace=*/true);9049  }9050 9051  void trackStatistics() const override {9052    STATS_DECLTRACK_FN_ATTR(denormal_fp_math)9053  }9054};9055} // namespace9056 9057/// ------------------ Value Constant Range Attribute -------------------------9058 9059namespace {9060struct AAValueConstantRangeImpl : AAValueConstantRange {9061  using StateType = IntegerRangeState;9062  AAValueConstantRangeImpl(const IRPosition &IRP, Attributor &A)9063      : AAValueConstantRange(IRP, A) {}9064 9065  /// See AbstractAttribute::initialize(..).9066  void initialize(Attributor &A) override {9067    if (A.hasSimplificationCallback(getIRPosition())) {9068      indicatePessimisticFixpoint();9069      return;9070    }9071 9072    // Intersect a range given by SCEV.9073    intersectKnown(getConstantRangeFromSCEV(A, getCtxI()));9074 9075    // Intersect a range given by LVI.9076    intersectKnown(getConstantRangeFromLVI(A, getCtxI()));9077  }9078 9079  /// See AbstractAttribute::getAsStr().9080  const std::string getAsStr(Attributor *A) const override {9081    std::string Str;9082    llvm::raw_string_ostream OS(Str);9083    OS << "range(" << getBitWidth() << ")<";9084    getKnown().print(OS);9085    OS << " / ";9086    getAssumed().print(OS);9087    OS << ">";9088    return Str;9089  }9090 9091  /// Helper function to get a SCEV expr for the associated value at program9092  /// point \p I.9093  const SCEV *getSCEV(Attributor &A, const Instruction *I = nullptr) const {9094    if (!getAnchorScope())9095      return nullptr;9096 9097    ScalarEvolution *SE =9098        A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(9099            *getAnchorScope());9100 9101    LoopInfo *LI = A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(9102        *getAnchorScope());9103 9104    if (!SE || !LI)9105      return nullptr;9106 9107    const SCEV *S = SE->getSCEV(&getAssociatedValue());9108    if (!I)9109      return S;9110 9111    return SE->getSCEVAtScope(S, LI->getLoopFor(I->getParent()));9112  }9113 9114  /// Helper function to get a range from SCEV for the associated value at9115  /// program point \p I.9116  ConstantRange getConstantRangeFromSCEV(Attributor &A,9117                                         const Instruction *I = nullptr) const {9118    if (!getAnchorScope())9119      return getWorstState(getBitWidth());9120 9121    ScalarEvolution *SE =9122        A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(9123            *getAnchorScope());9124 9125    const SCEV *S = getSCEV(A, I);9126    if (!SE || !S)9127      return getWorstState(getBitWidth());9128 9129    return SE->getUnsignedRange(S);9130  }9131 9132  /// Helper function to get a range from LVI for the associated value at9133  /// program point \p I.9134  ConstantRange9135  getConstantRangeFromLVI(Attributor &A,9136                          const Instruction *CtxI = nullptr) const {9137    if (!getAnchorScope())9138      return getWorstState(getBitWidth());9139 9140    LazyValueInfo *LVI =9141        A.getInfoCache().getAnalysisResultForFunction<LazyValueAnalysis>(9142            *getAnchorScope());9143 9144    if (!LVI || !CtxI)9145      return getWorstState(getBitWidth());9146    return LVI->getConstantRange(&getAssociatedValue(),9147                                 const_cast<Instruction *>(CtxI),9148                                 /*UndefAllowed*/ false);9149  }9150 9151  /// Return true if \p CtxI is valid for querying outside analyses.9152  /// This basically makes sure we do not ask intra-procedural analysis9153  /// about a context in the wrong function or a context that violates9154  /// dominance assumptions they might have. The \p AllowAACtxI flag indicates9155  /// if the original context of this AA is OK or should be considered invalid.9156  bool isValidCtxInstructionForOutsideAnalysis(Attributor &A,9157                                               const Instruction *CtxI,9158                                               bool AllowAACtxI) const {9159    if (!CtxI || (!AllowAACtxI && CtxI == getCtxI()))9160      return false;9161 9162    // Our context might be in a different function, neither intra-procedural9163    // analysis (ScalarEvolution nor LazyValueInfo) can handle that.9164    if (!AA::isValidInScope(getAssociatedValue(), CtxI->getFunction()))9165      return false;9166 9167    // If the context is not dominated by the value there are paths to the9168    // context that do not define the value. This cannot be handled by9169    // LazyValueInfo so we need to bail.9170    if (auto *I = dyn_cast<Instruction>(&getAssociatedValue())) {9171      InformationCache &InfoCache = A.getInfoCache();9172      const DominatorTree *DT =9173          InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(9174              *I->getFunction());9175      return DT && DT->dominates(I, CtxI);9176    }9177 9178    return true;9179  }9180 9181  /// See AAValueConstantRange::getKnownConstantRange(..).9182  ConstantRange9183  getKnownConstantRange(Attributor &A,9184                        const Instruction *CtxI = nullptr) const override {9185    if (!isValidCtxInstructionForOutsideAnalysis(A, CtxI,9186                                                 /* AllowAACtxI */ false))9187      return getKnown();9188 9189    ConstantRange LVIR = getConstantRangeFromLVI(A, CtxI);9190    ConstantRange SCEVR = getConstantRangeFromSCEV(A, CtxI);9191    return getKnown().intersectWith(SCEVR).intersectWith(LVIR);9192  }9193 9194  /// See AAValueConstantRange::getAssumedConstantRange(..).9195  ConstantRange9196  getAssumedConstantRange(Attributor &A,9197                          const Instruction *CtxI = nullptr) const override {9198    // TODO: Make SCEV use Attributor assumption.9199    //       We may be able to bound a variable range via assumptions in9200    //       Attributor. ex.) If x is assumed to be in [1, 3] and y is known to9201    //       evolve to x^2 + x, then we can say that y is in [2, 12].9202    if (!isValidCtxInstructionForOutsideAnalysis(A, CtxI,9203                                                 /* AllowAACtxI */ false))9204      return getAssumed();9205 9206    ConstantRange LVIR = getConstantRangeFromLVI(A, CtxI);9207    ConstantRange SCEVR = getConstantRangeFromSCEV(A, CtxI);9208    return getAssumed().intersectWith(SCEVR).intersectWith(LVIR);9209  }9210 9211  /// Helper function to create MDNode for range metadata.9212  static MDNode *9213  getMDNodeForConstantRange(Type *Ty, LLVMContext &Ctx,9214                            const ConstantRange &AssumedConstantRange) {9215    Metadata *LowAndHigh[] = {ConstantAsMetadata::get(ConstantInt::get(9216                                  Ty, AssumedConstantRange.getLower())),9217                              ConstantAsMetadata::get(ConstantInt::get(9218                                  Ty, AssumedConstantRange.getUpper()))};9219    return MDNode::get(Ctx, LowAndHigh);9220  }9221 9222  /// Return true if \p Assumed is included in ranges from instruction \p I.9223  static bool isBetterRange(const ConstantRange &Assumed,9224                            const Instruction &I) {9225    if (Assumed.isFullSet())9226      return false;9227 9228    std::optional<ConstantRange> Known;9229 9230    if (const auto *CB = dyn_cast<CallBase>(&I)) {9231      Known = CB->getRange();9232    } else if (MDNode *KnownRanges = I.getMetadata(LLVMContext::MD_range)) {9233      // If multiple ranges are annotated in IR, we give up to annotate assumed9234      // range for now.9235 9236      // TODO:  If there exists a known range which containts assumed range, we9237      // can say assumed range is better.9238      if (KnownRanges->getNumOperands() > 2)9239        return false;9240 9241      ConstantInt *Lower =9242          mdconst::extract<ConstantInt>(KnownRanges->getOperand(0));9243      ConstantInt *Upper =9244          mdconst::extract<ConstantInt>(KnownRanges->getOperand(1));9245 9246      Known.emplace(Lower->getValue(), Upper->getValue());9247    }9248    return !Known || (*Known != Assumed && Known->contains(Assumed));9249  }9250 9251  /// Helper function to set range metadata.9252  static bool9253  setRangeMetadataIfisBetterRange(Instruction *I,9254                                  const ConstantRange &AssumedConstantRange) {9255    if (isBetterRange(AssumedConstantRange, *I)) {9256      I->setMetadata(LLVMContext::MD_range,9257                     getMDNodeForConstantRange(I->getType(), I->getContext(),9258                                               AssumedConstantRange));9259      return true;9260    }9261    return false;9262  }9263  /// Helper function to set range return attribute.9264  static bool9265  setRangeRetAttrIfisBetterRange(Attributor &A, const IRPosition &IRP,9266                                 Instruction *I,9267                                 const ConstantRange &AssumedConstantRange) {9268    if (isBetterRange(AssumedConstantRange, *I)) {9269      A.manifestAttrs(IRP,9270                      Attribute::get(I->getContext(), Attribute::Range,9271                                     AssumedConstantRange),9272                      /*ForceReplace*/ true);9273      return true;9274    }9275    return false;9276  }9277 9278  /// See AbstractAttribute::manifest()9279  ChangeStatus manifest(Attributor &A) override {9280    ChangeStatus Changed = ChangeStatus::UNCHANGED;9281    ConstantRange AssumedConstantRange = getAssumedConstantRange(A);9282    assert(!AssumedConstantRange.isFullSet() && "Invalid state");9283 9284    auto &V = getAssociatedValue();9285    if (!AssumedConstantRange.isEmptySet() &&9286        !AssumedConstantRange.isSingleElement()) {9287      if (Instruction *I = dyn_cast<Instruction>(&V)) {9288        assert(I == getCtxI() && "Should not annotate an instruction which is "9289                                 "not the context instruction");9290        if (isa<LoadInst>(I))9291          if (setRangeMetadataIfisBetterRange(I, AssumedConstantRange))9292            Changed = ChangeStatus::CHANGED;9293        if (isa<CallInst>(I))9294          if (setRangeRetAttrIfisBetterRange(A, getIRPosition(), I,9295                                             AssumedConstantRange))9296            Changed = ChangeStatus::CHANGED;9297      }9298    }9299 9300    return Changed;9301  }9302};9303 9304struct AAValueConstantRangeArgument final9305    : AAArgumentFromCallSiteArguments<9306          AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,9307          true /* BridgeCallBaseContext */> {9308  using Base = AAArgumentFromCallSiteArguments<9309      AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,9310      true /* BridgeCallBaseContext */>;9311  AAValueConstantRangeArgument(const IRPosition &IRP, Attributor &A)9312      : Base(IRP, A) {}9313 9314  /// See AbstractAttribute::trackStatistics()9315  void trackStatistics() const override {9316    STATS_DECLTRACK_ARG_ATTR(value_range)9317  }9318};9319 9320struct AAValueConstantRangeReturned9321    : AAReturnedFromReturnedValues<AAValueConstantRange,9322                                   AAValueConstantRangeImpl,9323                                   AAValueConstantRangeImpl::StateType,9324                                   /* PropagateCallBaseContext */ true> {9325  using Base =9326      AAReturnedFromReturnedValues<AAValueConstantRange,9327                                   AAValueConstantRangeImpl,9328                                   AAValueConstantRangeImpl::StateType,9329                                   /* PropagateCallBaseContext */ true>;9330  AAValueConstantRangeReturned(const IRPosition &IRP, Attributor &A)9331      : Base(IRP, A) {}9332 9333  /// See AbstractAttribute::initialize(...).9334  void initialize(Attributor &A) override {9335    if (!A.isFunctionIPOAmendable(*getAssociatedFunction()))9336      indicatePessimisticFixpoint();9337  }9338 9339  /// See AbstractAttribute::trackStatistics()9340  void trackStatistics() const override {9341    STATS_DECLTRACK_FNRET_ATTR(value_range)9342  }9343};9344 9345struct AAValueConstantRangeFloating : AAValueConstantRangeImpl {9346  AAValueConstantRangeFloating(const IRPosition &IRP, Attributor &A)9347      : AAValueConstantRangeImpl(IRP, A) {}9348 9349  /// See AbstractAttribute::initialize(...).9350  void initialize(Attributor &A) override {9351    AAValueConstantRangeImpl::initialize(A);9352    if (isAtFixpoint())9353      return;9354 9355    Value &V = getAssociatedValue();9356 9357    if (auto *C = dyn_cast<ConstantInt>(&V)) {9358      unionAssumed(ConstantRange(C->getValue()));9359      indicateOptimisticFixpoint();9360      return;9361    }9362 9363    if (isa<UndefValue>(&V)) {9364      // Collapse the undef state to 0.9365      unionAssumed(ConstantRange(APInt(getBitWidth(), 0)));9366      indicateOptimisticFixpoint();9367      return;9368    }9369 9370    if (isa<CallBase>(&V))9371      return;9372 9373    if (isa<BinaryOperator>(&V) || isa<CmpInst>(&V) || isa<CastInst>(&V))9374      return;9375 9376    // If it is a load instruction with range metadata, use it.9377    if (LoadInst *LI = dyn_cast<LoadInst>(&V))9378      if (auto *RangeMD = LI->getMetadata(LLVMContext::MD_range)) {9379        intersectKnown(getConstantRangeFromMetadata(*RangeMD));9380        return;9381      }9382 9383    // We can work with PHI and select instruction as we traverse their operands9384    // during update.9385    if (isa<SelectInst>(V) || isa<PHINode>(V))9386      return;9387 9388    // Otherwise we give up.9389    indicatePessimisticFixpoint();9390 9391    LLVM_DEBUG(dbgs() << "[AAValueConstantRange] We give up: "9392                      << getAssociatedValue() << "\n");9393  }9394 9395  bool calculateBinaryOperator(9396      Attributor &A, BinaryOperator *BinOp, IntegerRangeState &T,9397      const Instruction *CtxI,9398      SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {9399    Value *LHS = BinOp->getOperand(0);9400    Value *RHS = BinOp->getOperand(1);9401 9402    // Simplify the operands first.9403    bool UsedAssumedInformation = false;9404    const auto &SimplifiedLHS = A.getAssumedSimplified(9405        IRPosition::value(*LHS, getCallBaseContext()), *this,9406        UsedAssumedInformation, AA::Interprocedural);9407    if (!SimplifiedLHS.has_value())9408      return true;9409    if (!*SimplifiedLHS)9410      return false;9411    LHS = *SimplifiedLHS;9412 9413    const auto &SimplifiedRHS = A.getAssumedSimplified(9414        IRPosition::value(*RHS, getCallBaseContext()), *this,9415        UsedAssumedInformation, AA::Interprocedural);9416    if (!SimplifiedRHS.has_value())9417      return true;9418    if (!*SimplifiedRHS)9419      return false;9420    RHS = *SimplifiedRHS;9421 9422    // TODO: Allow non integers as well.9423    if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy())9424      return false;9425 9426    auto *LHSAA = A.getAAFor<AAValueConstantRange>(9427        *this, IRPosition::value(*LHS, getCallBaseContext()),9428        DepClassTy::REQUIRED);9429    if (!LHSAA)9430      return false;9431    QuerriedAAs.push_back(LHSAA);9432    auto LHSAARange = LHSAA->getAssumedConstantRange(A, CtxI);9433 9434    auto *RHSAA = A.getAAFor<AAValueConstantRange>(9435        *this, IRPosition::value(*RHS, getCallBaseContext()),9436        DepClassTy::REQUIRED);9437    if (!RHSAA)9438      return false;9439    QuerriedAAs.push_back(RHSAA);9440    auto RHSAARange = RHSAA->getAssumedConstantRange(A, CtxI);9441 9442    auto AssumedRange = LHSAARange.binaryOp(BinOp->getOpcode(), RHSAARange);9443 9444    T.unionAssumed(AssumedRange);9445 9446    // TODO: Track a known state too.9447 9448    return T.isValidState();9449  }9450 9451  bool calculateCastInst(9452      Attributor &A, CastInst *CastI, IntegerRangeState &T,9453      const Instruction *CtxI,9454      SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {9455    assert(CastI->getNumOperands() == 1 && "Expected cast to be unary!");9456    // TODO: Allow non integers as well.9457    Value *OpV = CastI->getOperand(0);9458 9459    // Simplify the operand first.9460    bool UsedAssumedInformation = false;9461    const auto &SimplifiedOpV = A.getAssumedSimplified(9462        IRPosition::value(*OpV, getCallBaseContext()), *this,9463        UsedAssumedInformation, AA::Interprocedural);9464    if (!SimplifiedOpV.has_value())9465      return true;9466    if (!*SimplifiedOpV)9467      return false;9468    OpV = *SimplifiedOpV;9469 9470    if (!OpV->getType()->isIntegerTy())9471      return false;9472 9473    auto *OpAA = A.getAAFor<AAValueConstantRange>(9474        *this, IRPosition::value(*OpV, getCallBaseContext()),9475        DepClassTy::REQUIRED);9476    if (!OpAA)9477      return false;9478    QuerriedAAs.push_back(OpAA);9479    T.unionAssumed(OpAA->getAssumed().castOp(CastI->getOpcode(),9480                                             getState().getBitWidth()));9481    return T.isValidState();9482  }9483 9484  bool9485  calculateCmpInst(Attributor &A, CmpInst *CmpI, IntegerRangeState &T,9486                   const Instruction *CtxI,9487                   SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {9488    Value *LHS = CmpI->getOperand(0);9489    Value *RHS = CmpI->getOperand(1);9490 9491    // Simplify the operands first.9492    bool UsedAssumedInformation = false;9493    const auto &SimplifiedLHS = A.getAssumedSimplified(9494        IRPosition::value(*LHS, getCallBaseContext()), *this,9495        UsedAssumedInformation, AA::Interprocedural);9496    if (!SimplifiedLHS.has_value())9497      return true;9498    if (!*SimplifiedLHS)9499      return false;9500    LHS = *SimplifiedLHS;9501 9502    const auto &SimplifiedRHS = A.getAssumedSimplified(9503        IRPosition::value(*RHS, getCallBaseContext()), *this,9504        UsedAssumedInformation, AA::Interprocedural);9505    if (!SimplifiedRHS.has_value())9506      return true;9507    if (!*SimplifiedRHS)9508      return false;9509    RHS = *SimplifiedRHS;9510 9511    // TODO: Allow non integers as well.9512    if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy())9513      return false;9514 9515    auto *LHSAA = A.getAAFor<AAValueConstantRange>(9516        *this, IRPosition::value(*LHS, getCallBaseContext()),9517        DepClassTy::REQUIRED);9518    if (!LHSAA)9519      return false;9520    QuerriedAAs.push_back(LHSAA);9521    auto *RHSAA = A.getAAFor<AAValueConstantRange>(9522        *this, IRPosition::value(*RHS, getCallBaseContext()),9523        DepClassTy::REQUIRED);9524    if (!RHSAA)9525      return false;9526    QuerriedAAs.push_back(RHSAA);9527    auto LHSAARange = LHSAA->getAssumedConstantRange(A, CtxI);9528    auto RHSAARange = RHSAA->getAssumedConstantRange(A, CtxI);9529 9530    // If one of them is empty set, we can't decide.9531    if (LHSAARange.isEmptySet() || RHSAARange.isEmptySet())9532      return true;9533 9534    bool MustTrue = false, MustFalse = false;9535 9536    auto AllowedRegion =9537        ConstantRange::makeAllowedICmpRegion(CmpI->getPredicate(), RHSAARange);9538 9539    if (AllowedRegion.intersectWith(LHSAARange).isEmptySet())9540      MustFalse = true;9541 9542    if (LHSAARange.icmp(CmpI->getPredicate(), RHSAARange))9543      MustTrue = true;9544 9545    assert((!MustTrue || !MustFalse) &&9546           "Either MustTrue or MustFalse should be false!");9547 9548    if (MustTrue)9549      T.unionAssumed(ConstantRange(APInt(/* numBits */ 1, /* val */ 1)));9550    else if (MustFalse)9551      T.unionAssumed(ConstantRange(APInt(/* numBits */ 1, /* val */ 0)));9552    else9553      T.unionAssumed(ConstantRange(/* BitWidth */ 1, /* isFullSet */ true));9554 9555    LLVM_DEBUG(dbgs() << "[AAValueConstantRange] " << *CmpI << " after "9556                      << (MustTrue ? "true" : (MustFalse ? "false" : "unknown"))9557                      << ": " << T << "\n\t" << *LHSAA << "\t<op>\n\t"9558                      << *RHSAA);9559 9560    // TODO: Track a known state too.9561    return T.isValidState();9562  }9563 9564  /// See AbstractAttribute::updateImpl(...).9565  ChangeStatus updateImpl(Attributor &A) override {9566 9567    IntegerRangeState T(getBitWidth());9568    auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {9569      Instruction *I = dyn_cast<Instruction>(&V);9570      if (!I || isa<CallBase>(I)) {9571 9572        // Simplify the operand first.9573        bool UsedAssumedInformation = false;9574        const auto &SimplifiedOpV = A.getAssumedSimplified(9575            IRPosition::value(V, getCallBaseContext()), *this,9576            UsedAssumedInformation, AA::Interprocedural);9577        if (!SimplifiedOpV.has_value())9578          return true;9579        if (!*SimplifiedOpV)9580          return false;9581        Value *VPtr = *SimplifiedOpV;9582 9583        // If the value is not instruction, we query AA to Attributor.9584        const auto *AA = A.getAAFor<AAValueConstantRange>(9585            *this, IRPosition::value(*VPtr, getCallBaseContext()),9586            DepClassTy::REQUIRED);9587 9588        // Clamp operator is not used to utilize a program point CtxI.9589        if (AA)9590          T.unionAssumed(AA->getAssumedConstantRange(A, CtxI));9591        else9592          return false;9593 9594        return T.isValidState();9595      }9596 9597      SmallVector<const AAValueConstantRange *, 4> QuerriedAAs;9598      if (auto *BinOp = dyn_cast<BinaryOperator>(I)) {9599        if (!calculateBinaryOperator(A, BinOp, T, CtxI, QuerriedAAs))9600          return false;9601      } else if (auto *CmpI = dyn_cast<CmpInst>(I)) {9602        if (!calculateCmpInst(A, CmpI, T, CtxI, QuerriedAAs))9603          return false;9604      } else if (auto *CastI = dyn_cast<CastInst>(I)) {9605        if (!calculateCastInst(A, CastI, T, CtxI, QuerriedAAs))9606          return false;9607      } else {9608        // Give up with other instructions.9609        // TODO: Add other instructions9610 9611        T.indicatePessimisticFixpoint();9612        return false;9613      }9614 9615      // Catch circular reasoning in a pessimistic way for now.9616      // TODO: Check how the range evolves and if we stripped anything, see also9617      //       AADereferenceable or AAAlign for similar situations.9618      for (const AAValueConstantRange *QueriedAA : QuerriedAAs) {9619        if (QueriedAA != this)9620          continue;9621        // If we are in a stady state we do not need to worry.9622        if (T.getAssumed() == getState().getAssumed())9623          continue;9624        T.indicatePessimisticFixpoint();9625      }9626 9627      return T.isValidState();9628    };9629 9630    if (!VisitValueCB(getAssociatedValue(), getCtxI()))9631      return indicatePessimisticFixpoint();9632 9633    // Ensure that long def-use chains can't cause circular reasoning either by9634    // introducing a cutoff below.9635    if (clampStateAndIndicateChange(getState(), T) == ChangeStatus::UNCHANGED)9636      return ChangeStatus::UNCHANGED;9637    if (++NumChanges > MaxNumChanges) {9638      LLVM_DEBUG(dbgs() << "[AAValueConstantRange] performed " << NumChanges9639                        << " but only " << MaxNumChanges9640                        << " are allowed to avoid cyclic reasoning.");9641      return indicatePessimisticFixpoint();9642    }9643    return ChangeStatus::CHANGED;9644  }9645 9646  /// See AbstractAttribute::trackStatistics()9647  void trackStatistics() const override {9648    STATS_DECLTRACK_FLOATING_ATTR(value_range)9649  }9650 9651  /// Tracker to bail after too many widening steps of the constant range.9652  int NumChanges = 0;9653 9654  /// Upper bound for the number of allowed changes (=widening steps) for the9655  /// constant range before we give up.9656  static constexpr int MaxNumChanges = 5;9657};9658 9659struct AAValueConstantRangeFunction : AAValueConstantRangeImpl {9660  AAValueConstantRangeFunction(const IRPosition &IRP, Attributor &A)9661      : AAValueConstantRangeImpl(IRP, A) {}9662 9663  /// See AbstractAttribute::initialize(...).9664  ChangeStatus updateImpl(Attributor &A) override {9665    llvm_unreachable("AAValueConstantRange(Function|CallSite)::updateImpl will "9666                     "not be called");9667  }9668 9669  /// See AbstractAttribute::trackStatistics()9670  void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(value_range) }9671};9672 9673struct AAValueConstantRangeCallSite : AAValueConstantRangeFunction {9674  AAValueConstantRangeCallSite(const IRPosition &IRP, Attributor &A)9675      : AAValueConstantRangeFunction(IRP, A) {}9676 9677  /// See AbstractAttribute::trackStatistics()9678  void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(value_range) }9679};9680 9681struct AAValueConstantRangeCallSiteReturned9682    : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,9683                         AAValueConstantRangeImpl::StateType,9684                         /* IntroduceCallBaseContext */ true> {9685  AAValueConstantRangeCallSiteReturned(const IRPosition &IRP, Attributor &A)9686      : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,9687                           AAValueConstantRangeImpl::StateType,9688                           /* IntroduceCallBaseContext */ true>(IRP, A) {}9689 9690  /// See AbstractAttribute::initialize(...).9691  void initialize(Attributor &A) override {9692    // If it is a call instruction with range attribute, use the range.9693    if (CallInst *CI = dyn_cast<CallInst>(&getAssociatedValue())) {9694      if (std::optional<ConstantRange> Range = CI->getRange())9695        intersectKnown(*Range);9696    }9697 9698    AAValueConstantRangeImpl::initialize(A);9699  }9700 9701  /// See AbstractAttribute::trackStatistics()9702  void trackStatistics() const override {9703    STATS_DECLTRACK_CSRET_ATTR(value_range)9704  }9705};9706struct AAValueConstantRangeCallSiteArgument : AAValueConstantRangeFloating {9707  AAValueConstantRangeCallSiteArgument(const IRPosition &IRP, Attributor &A)9708      : AAValueConstantRangeFloating(IRP, A) {}9709 9710  /// See AbstractAttribute::manifest()9711  ChangeStatus manifest(Attributor &A) override {9712    return ChangeStatus::UNCHANGED;9713  }9714 9715  /// See AbstractAttribute::trackStatistics()9716  void trackStatistics() const override {9717    STATS_DECLTRACK_CSARG_ATTR(value_range)9718  }9719};9720} // namespace9721 9722/// ------------------ Potential Values Attribute -------------------------9723 9724namespace {9725struct AAPotentialConstantValuesImpl : AAPotentialConstantValues {9726  using StateType = PotentialConstantIntValuesState;9727 9728  AAPotentialConstantValuesImpl(const IRPosition &IRP, Attributor &A)9729      : AAPotentialConstantValues(IRP, A) {}9730 9731  /// See AbstractAttribute::initialize(..).9732  void initialize(Attributor &A) override {9733    if (A.hasSimplificationCallback(getIRPosition()))9734      indicatePessimisticFixpoint();9735    else9736      AAPotentialConstantValues::initialize(A);9737  }9738 9739  bool fillSetWithConstantValues(Attributor &A, const IRPosition &IRP, SetTy &S,9740                                 bool &ContainsUndef, bool ForSelf) {9741    SmallVector<AA::ValueAndContext> Values;9742    bool UsedAssumedInformation = false;9743    if (!A.getAssumedSimplifiedValues(IRP, *this, Values, AA::Interprocedural,9744                                      UsedAssumedInformation)) {9745      // Avoid recursion when the caller is computing constant values for this9746      // IRP itself.9747      if (ForSelf)9748        return false;9749      if (!IRP.getAssociatedType()->isIntegerTy())9750        return false;9751      auto *PotentialValuesAA = A.getAAFor<AAPotentialConstantValues>(9752          *this, IRP, DepClassTy::REQUIRED);9753      if (!PotentialValuesAA || !PotentialValuesAA->getState().isValidState())9754        return false;9755      ContainsUndef = PotentialValuesAA->getState().undefIsContained();9756      S = PotentialValuesAA->getState().getAssumedSet();9757      return true;9758    }9759 9760    // Copy all the constant values, except UndefValue. ContainsUndef is true9761    // iff Values contains only UndefValue instances. If there are other known9762    // constants, then UndefValue is dropped.9763    ContainsUndef = false;9764    for (auto &It : Values) {9765      if (isa<UndefValue>(It.getValue())) {9766        ContainsUndef = true;9767        continue;9768      }9769      auto *CI = dyn_cast<ConstantInt>(It.getValue());9770      if (!CI)9771        return false;9772      S.insert(CI->getValue());9773    }9774    ContainsUndef &= S.empty();9775 9776    return true;9777  }9778 9779  /// See AbstractAttribute::getAsStr().9780  const std::string getAsStr(Attributor *A) const override {9781    std::string Str;9782    llvm::raw_string_ostream OS(Str);9783    OS << getState();9784    return Str;9785  }9786 9787  /// See AbstractAttribute::updateImpl(...).9788  ChangeStatus updateImpl(Attributor &A) override {9789    return indicatePessimisticFixpoint();9790  }9791};9792 9793struct AAPotentialConstantValuesArgument final9794    : AAArgumentFromCallSiteArguments<AAPotentialConstantValues,9795                                      AAPotentialConstantValuesImpl,9796                                      PotentialConstantIntValuesState> {9797  using Base = AAArgumentFromCallSiteArguments<AAPotentialConstantValues,9798                                               AAPotentialConstantValuesImpl,9799                                               PotentialConstantIntValuesState>;9800  AAPotentialConstantValuesArgument(const IRPosition &IRP, Attributor &A)9801      : Base(IRP, A) {}9802 9803  /// See AbstractAttribute::trackStatistics()9804  void trackStatistics() const override {9805    STATS_DECLTRACK_ARG_ATTR(potential_values)9806  }9807};9808 9809struct AAPotentialConstantValuesReturned9810    : AAReturnedFromReturnedValues<AAPotentialConstantValues,9811                                   AAPotentialConstantValuesImpl> {9812  using Base = AAReturnedFromReturnedValues<AAPotentialConstantValues,9813                                            AAPotentialConstantValuesImpl>;9814  AAPotentialConstantValuesReturned(const IRPosition &IRP, Attributor &A)9815      : Base(IRP, A) {}9816 9817  void initialize(Attributor &A) override {9818    if (!A.isFunctionIPOAmendable(*getAssociatedFunction()))9819      indicatePessimisticFixpoint();9820    Base::initialize(A);9821  }9822 9823  /// See AbstractAttribute::trackStatistics()9824  void trackStatistics() const override {9825    STATS_DECLTRACK_FNRET_ATTR(potential_values)9826  }9827};9828 9829struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {9830  AAPotentialConstantValuesFloating(const IRPosition &IRP, Attributor &A)9831      : AAPotentialConstantValuesImpl(IRP, A) {}9832 9833  /// See AbstractAttribute::initialize(..).9834  void initialize(Attributor &A) override {9835    AAPotentialConstantValuesImpl::initialize(A);9836    if (isAtFixpoint())9837      return;9838 9839    Value &V = getAssociatedValue();9840 9841    if (auto *C = dyn_cast<ConstantInt>(&V)) {9842      unionAssumed(C->getValue());9843      indicateOptimisticFixpoint();9844      return;9845    }9846 9847    if (isa<UndefValue>(&V)) {9848      unionAssumedWithUndef();9849      indicateOptimisticFixpoint();9850      return;9851    }9852 9853    if (isa<BinaryOperator>(&V) || isa<ICmpInst>(&V) || isa<CastInst>(&V))9854      return;9855 9856    if (isa<SelectInst>(V) || isa<PHINode>(V) || isa<LoadInst>(V))9857      return;9858 9859    indicatePessimisticFixpoint();9860 9861    LLVM_DEBUG(dbgs() << "[AAPotentialConstantValues] We give up: "9862                      << getAssociatedValue() << "\n");9863  }9864 9865  static bool calculateICmpInst(const ICmpInst *ICI, const APInt &LHS,9866                                const APInt &RHS) {9867    return ICmpInst::compare(LHS, RHS, ICI->getPredicate());9868  }9869 9870  static APInt calculateCastInst(const CastInst *CI, const APInt &Src,9871                                 uint32_t ResultBitWidth) {9872    Instruction::CastOps CastOp = CI->getOpcode();9873    switch (CastOp) {9874    default:9875      llvm_unreachable("unsupported or not integer cast");9876    case Instruction::Trunc:9877      return Src.trunc(ResultBitWidth);9878    case Instruction::SExt:9879      return Src.sext(ResultBitWidth);9880    case Instruction::ZExt:9881      return Src.zext(ResultBitWidth);9882    case Instruction::BitCast:9883      return Src;9884    }9885  }9886 9887  static APInt calculateBinaryOperator(const BinaryOperator *BinOp,9888                                       const APInt &LHS, const APInt &RHS,9889                                       bool &SkipOperation, bool &Unsupported) {9890    Instruction::BinaryOps BinOpcode = BinOp->getOpcode();9891    // Unsupported is set to true when the binary operator is not supported.9892    // SkipOperation is set to true when UB occur with the given operand pair9893    // (LHS, RHS).9894    // TODO: we should look at nsw and nuw keywords to handle operations9895    //       that create poison or undef value.9896    switch (BinOpcode) {9897    default:9898      Unsupported = true;9899      return LHS;9900    case Instruction::Add:9901      return LHS + RHS;9902    case Instruction::Sub:9903      return LHS - RHS;9904    case Instruction::Mul:9905      return LHS * RHS;9906    case Instruction::UDiv:9907      if (RHS.isZero()) {9908        SkipOperation = true;9909        return LHS;9910      }9911      return LHS.udiv(RHS);9912    case Instruction::SDiv:9913      if (RHS.isZero()) {9914        SkipOperation = true;9915        return LHS;9916      }9917      return LHS.sdiv(RHS);9918    case Instruction::URem:9919      if (RHS.isZero()) {9920        SkipOperation = true;9921        return LHS;9922      }9923      return LHS.urem(RHS);9924    case Instruction::SRem:9925      if (RHS.isZero()) {9926        SkipOperation = true;9927        return LHS;9928      }9929      return LHS.srem(RHS);9930    case Instruction::Shl:9931      return LHS.shl(RHS);9932    case Instruction::LShr:9933      return LHS.lshr(RHS);9934    case Instruction::AShr:9935      return LHS.ashr(RHS);9936    case Instruction::And:9937      return LHS & RHS;9938    case Instruction::Or:9939      return LHS | RHS;9940    case Instruction::Xor:9941      return LHS ^ RHS;9942    }9943  }9944 9945  bool calculateBinaryOperatorAndTakeUnion(const BinaryOperator *BinOp,9946                                           const APInt &LHS, const APInt &RHS) {9947    bool SkipOperation = false;9948    bool Unsupported = false;9949    APInt Result =9950        calculateBinaryOperator(BinOp, LHS, RHS, SkipOperation, Unsupported);9951    if (Unsupported)9952      return false;9953    // If SkipOperation is true, we can ignore this operand pair (L, R).9954    if (!SkipOperation)9955      unionAssumed(Result);9956    return isValidState();9957  }9958 9959  ChangeStatus updateWithICmpInst(Attributor &A, ICmpInst *ICI) {9960    auto AssumedBefore = getAssumed();9961    Value *LHS = ICI->getOperand(0);9962    Value *RHS = ICI->getOperand(1);9963 9964    bool LHSContainsUndef = false, RHSContainsUndef = false;9965    SetTy LHSAAPVS, RHSAAPVS;9966    if (!fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,9967                                   LHSContainsUndef, /* ForSelf */ false) ||9968        !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,9969                                   RHSContainsUndef, /* ForSelf */ false))9970      return indicatePessimisticFixpoint();9971 9972    // TODO: make use of undef flag to limit potential values aggressively.9973    bool MaybeTrue = false, MaybeFalse = false;9974    const APInt Zero(RHS->getType()->getIntegerBitWidth(), 0);9975    if (LHSContainsUndef && RHSContainsUndef) {9976      // The result of any comparison between undefs can be soundly replaced9977      // with undef.9978      unionAssumedWithUndef();9979    } else if (LHSContainsUndef) {9980      for (const APInt &R : RHSAAPVS) {9981        bool CmpResult = calculateICmpInst(ICI, Zero, R);9982        MaybeTrue |= CmpResult;9983        MaybeFalse |= !CmpResult;9984        if (MaybeTrue & MaybeFalse)9985          return indicatePessimisticFixpoint();9986      }9987    } else if (RHSContainsUndef) {9988      for (const APInt &L : LHSAAPVS) {9989        bool CmpResult = calculateICmpInst(ICI, L, Zero);9990        MaybeTrue |= CmpResult;9991        MaybeFalse |= !CmpResult;9992        if (MaybeTrue & MaybeFalse)9993          return indicatePessimisticFixpoint();9994      }9995    } else {9996      for (const APInt &L : LHSAAPVS) {9997        for (const APInt &R : RHSAAPVS) {9998          bool CmpResult = calculateICmpInst(ICI, L, R);9999          MaybeTrue |= CmpResult;10000          MaybeFalse |= !CmpResult;10001          if (MaybeTrue & MaybeFalse)10002            return indicatePessimisticFixpoint();10003        }10004      }10005    }10006    if (MaybeTrue)10007      unionAssumed(APInt(/* numBits */ 1, /* val */ 1));10008    if (MaybeFalse)10009      unionAssumed(APInt(/* numBits */ 1, /* val */ 0));10010    return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED10011                                         : ChangeStatus::CHANGED;10012  }10013 10014  ChangeStatus updateWithSelectInst(Attributor &A, SelectInst *SI) {10015    auto AssumedBefore = getAssumed();10016    Value *LHS = SI->getTrueValue();10017    Value *RHS = SI->getFalseValue();10018 10019    bool UsedAssumedInformation = false;10020    std::optional<Constant *> C = A.getAssumedConstant(10021        *SI->getCondition(), *this, UsedAssumedInformation);10022 10023    // Check if we only need one operand.10024    bool OnlyLeft = false, OnlyRight = false;10025    if (C && *C && (*C)->isOneValue())10026      OnlyLeft = true;10027    else if (C && *C && (*C)->isZeroValue())10028      OnlyRight = true;10029 10030    bool LHSContainsUndef = false, RHSContainsUndef = false;10031    SetTy LHSAAPVS, RHSAAPVS;10032    if (!OnlyRight &&10033        !fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,10034                                   LHSContainsUndef, /* ForSelf */ false))10035      return indicatePessimisticFixpoint();10036 10037    if (!OnlyLeft &&10038        !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,10039                                   RHSContainsUndef, /* ForSelf */ false))10040      return indicatePessimisticFixpoint();10041 10042    if (OnlyLeft || OnlyRight) {10043      // select (true/false), lhs, rhs10044      auto *OpAA = OnlyLeft ? &LHSAAPVS : &RHSAAPVS;10045      auto Undef = OnlyLeft ? LHSContainsUndef : RHSContainsUndef;10046 10047      if (Undef)10048        unionAssumedWithUndef();10049      else {10050        for (const auto &It : *OpAA)10051          unionAssumed(It);10052      }10053 10054    } else if (LHSContainsUndef && RHSContainsUndef) {10055      // select i1 *, undef , undef => undef10056      unionAssumedWithUndef();10057    } else {10058      for (const auto &It : LHSAAPVS)10059        unionAssumed(It);10060      for (const auto &It : RHSAAPVS)10061        unionAssumed(It);10062    }10063    return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED10064                                         : ChangeStatus::CHANGED;10065  }10066 10067  ChangeStatus updateWithCastInst(Attributor &A, CastInst *CI) {10068    auto AssumedBefore = getAssumed();10069    if (!CI->isIntegerCast())10070      return indicatePessimisticFixpoint();10071    assert(CI->getNumOperands() == 1 && "Expected cast to be unary!");10072    uint32_t ResultBitWidth = CI->getDestTy()->getIntegerBitWidth();10073    Value *Src = CI->getOperand(0);10074 10075    bool SrcContainsUndef = false;10076    SetTy SrcPVS;10077    if (!fillSetWithConstantValues(A, IRPosition::value(*Src), SrcPVS,10078                                   SrcContainsUndef, /* ForSelf */ false))10079      return indicatePessimisticFixpoint();10080 10081    if (SrcContainsUndef)10082      unionAssumedWithUndef();10083    else {10084      for (const APInt &S : SrcPVS) {10085        APInt T = calculateCastInst(CI, S, ResultBitWidth);10086        unionAssumed(T);10087      }10088    }10089    return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED10090                                         : ChangeStatus::CHANGED;10091  }10092 10093  ChangeStatus updateWithBinaryOperator(Attributor &A, BinaryOperator *BinOp) {10094    auto AssumedBefore = getAssumed();10095    Value *LHS = BinOp->getOperand(0);10096    Value *RHS = BinOp->getOperand(1);10097 10098    bool LHSContainsUndef = false, RHSContainsUndef = false;10099    SetTy LHSAAPVS, RHSAAPVS;10100    if (!fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,10101                                   LHSContainsUndef, /* ForSelf */ false) ||10102        !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,10103                                   RHSContainsUndef, /* ForSelf */ false))10104      return indicatePessimisticFixpoint();10105 10106    const APInt Zero = APInt(LHS->getType()->getIntegerBitWidth(), 0);10107 10108    // TODO: make use of undef flag to limit potential values aggressively.10109    if (LHSContainsUndef && RHSContainsUndef) {10110      if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, Zero))10111        return indicatePessimisticFixpoint();10112    } else if (LHSContainsUndef) {10113      for (const APInt &R : RHSAAPVS) {10114        if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, R))10115          return indicatePessimisticFixpoint();10116      }10117    } else if (RHSContainsUndef) {10118      for (const APInt &L : LHSAAPVS) {10119        if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, Zero))10120          return indicatePessimisticFixpoint();10121      }10122    } else {10123      for (const APInt &L : LHSAAPVS) {10124        for (const APInt &R : RHSAAPVS) {10125          if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, R))10126            return indicatePessimisticFixpoint();10127        }10128      }10129    }10130    return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED10131                                         : ChangeStatus::CHANGED;10132  }10133 10134  ChangeStatus updateWithInstruction(Attributor &A, Instruction *Inst) {10135    auto AssumedBefore = getAssumed();10136    SetTy Incoming;10137    bool ContainsUndef;10138    if (!fillSetWithConstantValues(A, IRPosition::value(*Inst), Incoming,10139                                   ContainsUndef, /* ForSelf */ true))10140      return indicatePessimisticFixpoint();10141    if (ContainsUndef) {10142      unionAssumedWithUndef();10143    } else {10144      for (const auto &It : Incoming)10145        unionAssumed(It);10146    }10147    return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED10148                                         : ChangeStatus::CHANGED;10149  }10150 10151  /// See AbstractAttribute::updateImpl(...).10152  ChangeStatus updateImpl(Attributor &A) override {10153    Value &V = getAssociatedValue();10154    Instruction *I = dyn_cast<Instruction>(&V);10155 10156    if (auto *ICI = dyn_cast<ICmpInst>(I))10157      return updateWithICmpInst(A, ICI);10158 10159    if (auto *SI = dyn_cast<SelectInst>(I))10160      return updateWithSelectInst(A, SI);10161 10162    if (auto *CI = dyn_cast<CastInst>(I))10163      return updateWithCastInst(A, CI);10164 10165    if (auto *BinOp = dyn_cast<BinaryOperator>(I))10166      return updateWithBinaryOperator(A, BinOp);10167 10168    if (isa<PHINode>(I) || isa<LoadInst>(I))10169      return updateWithInstruction(A, I);10170 10171    return indicatePessimisticFixpoint();10172  }10173 10174  /// See AbstractAttribute::trackStatistics()10175  void trackStatistics() const override {10176    STATS_DECLTRACK_FLOATING_ATTR(potential_values)10177  }10178};10179 10180struct AAPotentialConstantValuesFunction : AAPotentialConstantValuesImpl {10181  AAPotentialConstantValuesFunction(const IRPosition &IRP, Attributor &A)10182      : AAPotentialConstantValuesImpl(IRP, A) {}10183 10184  /// See AbstractAttribute::initialize(...).10185  ChangeStatus updateImpl(Attributor &A) override {10186    llvm_unreachable(10187        "AAPotentialConstantValues(Function|CallSite)::updateImpl will "10188        "not be called");10189  }10190 10191  /// See AbstractAttribute::trackStatistics()10192  void trackStatistics() const override {10193    STATS_DECLTRACK_FN_ATTR(potential_values)10194  }10195};10196 10197struct AAPotentialConstantValuesCallSite : AAPotentialConstantValuesFunction {10198  AAPotentialConstantValuesCallSite(const IRPosition &IRP, Attributor &A)10199      : AAPotentialConstantValuesFunction(IRP, A) {}10200 10201  /// See AbstractAttribute::trackStatistics()10202  void trackStatistics() const override {10203    STATS_DECLTRACK_CS_ATTR(potential_values)10204  }10205};10206 10207struct AAPotentialConstantValuesCallSiteReturned10208    : AACalleeToCallSite<AAPotentialConstantValues,10209                         AAPotentialConstantValuesImpl> {10210  AAPotentialConstantValuesCallSiteReturned(const IRPosition &IRP,10211                                            Attributor &A)10212      : AACalleeToCallSite<AAPotentialConstantValues,10213                           AAPotentialConstantValuesImpl>(IRP, A) {}10214 10215  /// See AbstractAttribute::trackStatistics()10216  void trackStatistics() const override {10217    STATS_DECLTRACK_CSRET_ATTR(potential_values)10218  }10219};10220 10221struct AAPotentialConstantValuesCallSiteArgument10222    : AAPotentialConstantValuesFloating {10223  AAPotentialConstantValuesCallSiteArgument(const IRPosition &IRP,10224                                            Attributor &A)10225      : AAPotentialConstantValuesFloating(IRP, A) {}10226 10227  /// See AbstractAttribute::initialize(..).10228  void initialize(Attributor &A) override {10229    AAPotentialConstantValuesImpl::initialize(A);10230    if (isAtFixpoint())10231      return;10232 10233    Value &V = getAssociatedValue();10234 10235    if (auto *C = dyn_cast<ConstantInt>(&V)) {10236      unionAssumed(C->getValue());10237      indicateOptimisticFixpoint();10238      return;10239    }10240 10241    if (isa<UndefValue>(&V)) {10242      unionAssumedWithUndef();10243      indicateOptimisticFixpoint();10244      return;10245    }10246  }10247 10248  /// See AbstractAttribute::updateImpl(...).10249  ChangeStatus updateImpl(Attributor &A) override {10250    Value &V = getAssociatedValue();10251    auto AssumedBefore = getAssumed();10252    auto *AA = A.getAAFor<AAPotentialConstantValues>(10253        *this, IRPosition::value(V), DepClassTy::REQUIRED);10254    if (!AA)10255      return indicatePessimisticFixpoint();10256    const auto &S = AA->getAssumed();10257    unionAssumed(S);10258    return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED10259                                         : ChangeStatus::CHANGED;10260  }10261 10262  /// See AbstractAttribute::trackStatistics()10263  void trackStatistics() const override {10264    STATS_DECLTRACK_CSARG_ATTR(potential_values)10265  }10266};10267} // namespace10268 10269/// ------------------------ NoUndef Attribute ---------------------------------10270bool AANoUndef::isImpliedByIR(Attributor &A, const IRPosition &IRP,10271                              Attribute::AttrKind ImpliedAttributeKind,10272                              bool IgnoreSubsumingPositions) {10273  assert(ImpliedAttributeKind == Attribute::NoUndef &&10274         "Unexpected attribute kind");10275  if (A.hasAttr(IRP, {Attribute::NoUndef}, IgnoreSubsumingPositions,10276                Attribute::NoUndef))10277    return true;10278 10279  Value &Val = IRP.getAssociatedValue();10280  if (IRP.getPositionKind() != IRPosition::IRP_RETURNED &&10281      isGuaranteedNotToBeUndefOrPoison(&Val)) {10282    LLVMContext &Ctx = Val.getContext();10283    A.manifestAttrs(IRP, Attribute::get(Ctx, Attribute::NoUndef));10284    return true;10285  }10286 10287  return false;10288}10289 10290namespace {10291struct AANoUndefImpl : AANoUndef {10292  AANoUndefImpl(const IRPosition &IRP, Attributor &A) : AANoUndef(IRP, A) {}10293 10294  /// See AbstractAttribute::initialize(...).10295  void initialize(Attributor &A) override {10296    Value &V = getAssociatedValue();10297    if (isa<UndefValue>(V))10298      indicatePessimisticFixpoint();10299    assert(!isImpliedByIR(A, getIRPosition(), Attribute::NoUndef));10300  }10301 10302  /// See followUsesInMBEC10303  bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,10304                       AANoUndef::StateType &State) {10305    const Value *UseV = U->get();10306    const DominatorTree *DT = nullptr;10307    AssumptionCache *AC = nullptr;10308    InformationCache &InfoCache = A.getInfoCache();10309    if (Function *F = getAnchorScope()) {10310      DT = InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);10311      AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);10312    }10313    State.setKnown(isGuaranteedNotToBeUndefOrPoison(UseV, AC, I, DT));10314    bool TrackUse = false;10315    // Track use for instructions which must produce undef or poison bits when10316    // at least one operand contains such bits.10317    if (isa<CastInst>(*I) || isa<GetElementPtrInst>(*I))10318      TrackUse = true;10319    return TrackUse;10320  }10321 10322  /// See AbstractAttribute::getAsStr().10323  const std::string getAsStr(Attributor *A) const override {10324    return getAssumed() ? "noundef" : "may-undef-or-poison";10325  }10326 10327  ChangeStatus manifest(Attributor &A) override {10328    // We don't manifest noundef attribute for dead positions because the10329    // associated values with dead positions would be replaced with undef10330    // values.10331    bool UsedAssumedInformation = false;10332    if (A.isAssumedDead(getIRPosition(), nullptr, nullptr,10333                        UsedAssumedInformation))10334      return ChangeStatus::UNCHANGED;10335    // A position whose simplified value does not have any value is10336    // considered to be dead. We don't manifest noundef in such positions for10337    // the same reason above.10338    if (!A.getAssumedSimplified(getIRPosition(), *this, UsedAssumedInformation,10339                                AA::Interprocedural)10340             .has_value())10341      return ChangeStatus::UNCHANGED;10342    return AANoUndef::manifest(A);10343  }10344};10345 10346struct AANoUndefFloating : public AANoUndefImpl {10347  AANoUndefFloating(const IRPosition &IRP, Attributor &A)10348      : AANoUndefImpl(IRP, A) {}10349 10350  /// See AbstractAttribute::initialize(...).10351  void initialize(Attributor &A) override {10352    AANoUndefImpl::initialize(A);10353    if (!getState().isAtFixpoint() && getAnchorScope() &&10354        !getAnchorScope()->isDeclaration())10355      if (Instruction *CtxI = getCtxI())10356        followUsesInMBEC(*this, A, getState(), *CtxI);10357  }10358 10359  /// See AbstractAttribute::updateImpl(...).10360  ChangeStatus updateImpl(Attributor &A) override {10361    auto VisitValueCB = [&](const IRPosition &IRP) -> bool {10362      bool IsKnownNoUndef;10363      return AA::hasAssumedIRAttr<Attribute::NoUndef>(10364          A, this, IRP, DepClassTy::REQUIRED, IsKnownNoUndef);10365    };10366 10367    bool Stripped;10368    bool UsedAssumedInformation = false;10369    Value *AssociatedValue = &getAssociatedValue();10370    SmallVector<AA::ValueAndContext> Values;10371    if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,10372                                      AA::AnyScope, UsedAssumedInformation))10373      Stripped = false;10374    else10375      Stripped =10376          Values.size() != 1 || Values.front().getValue() != AssociatedValue;10377 10378    if (!Stripped) {10379      // If we haven't stripped anything we might still be able to use a10380      // different AA, but only if the IRP changes. Effectively when we10381      // interpret this not as a call site value but as a floating/argument10382      // value.10383      const IRPosition AVIRP = IRPosition::value(*AssociatedValue);10384      if (AVIRP == getIRPosition() || !VisitValueCB(AVIRP))10385        return indicatePessimisticFixpoint();10386      return ChangeStatus::UNCHANGED;10387    }10388 10389    for (const auto &VAC : Values)10390      if (!VisitValueCB(IRPosition::value(*VAC.getValue())))10391        return indicatePessimisticFixpoint();10392 10393    return ChangeStatus::UNCHANGED;10394  }10395 10396  /// See AbstractAttribute::trackStatistics()10397  void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noundef) }10398};10399 10400struct AANoUndefReturned final10401    : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl> {10402  AANoUndefReturned(const IRPosition &IRP, Attributor &A)10403      : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>(IRP, A) {}10404 10405  /// See AbstractAttribute::trackStatistics()10406  void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noundef) }10407};10408 10409struct AANoUndefArgument final10410    : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl> {10411  AANoUndefArgument(const IRPosition &IRP, Attributor &A)10412      : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl>(IRP, A) {}10413 10414  /// See AbstractAttribute::trackStatistics()10415  void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noundef) }10416};10417 10418struct AANoUndefCallSiteArgument final : AANoUndefFloating {10419  AANoUndefCallSiteArgument(const IRPosition &IRP, Attributor &A)10420      : AANoUndefFloating(IRP, A) {}10421 10422  /// See AbstractAttribute::trackStatistics()10423  void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(noundef) }10424};10425 10426struct AANoUndefCallSiteReturned final10427    : AACalleeToCallSite<AANoUndef, AANoUndefImpl> {10428  AANoUndefCallSiteReturned(const IRPosition &IRP, Attributor &A)10429      : AACalleeToCallSite<AANoUndef, AANoUndefImpl>(IRP, A) {}10430 10431  /// See AbstractAttribute::trackStatistics()10432  void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noundef) }10433};10434 10435/// ------------------------ NoFPClass Attribute -------------------------------10436 10437struct AANoFPClassImpl : AANoFPClass {10438  AANoFPClassImpl(const IRPosition &IRP, Attributor &A) : AANoFPClass(IRP, A) {}10439 10440  void initialize(Attributor &A) override {10441    const IRPosition &IRP = getIRPosition();10442 10443    Value &V = IRP.getAssociatedValue();10444    if (isa<UndefValue>(V)) {10445      indicateOptimisticFixpoint();10446      return;10447    }10448 10449    SmallVector<Attribute> Attrs;10450    A.getAttrs(getIRPosition(), {Attribute::NoFPClass}, Attrs, false);10451    for (const auto &Attr : Attrs) {10452      addKnownBits(Attr.getNoFPClass());10453    }10454 10455    const DataLayout &DL = A.getDataLayout();10456    if (getPositionKind() != IRPosition::IRP_RETURNED) {10457      KnownFPClass KnownFPClass = computeKnownFPClass(&V, DL);10458      addKnownBits(~KnownFPClass.KnownFPClasses);10459    }10460 10461    if (Instruction *CtxI = getCtxI())10462      followUsesInMBEC(*this, A, getState(), *CtxI);10463  }10464 10465  /// See followUsesInMBEC10466  bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,10467                       AANoFPClass::StateType &State) {10468    // TODO: Determine what instructions can be looked through.10469    auto *CB = dyn_cast<CallBase>(I);10470    if (!CB)10471      return false;10472 10473    if (!CB->isArgOperand(U))10474      return false;10475 10476    unsigned ArgNo = CB->getArgOperandNo(U);10477    IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);10478    if (auto *NoFPAA = A.getAAFor<AANoFPClass>(*this, IRP, DepClassTy::NONE))10479      State.addKnownBits(NoFPAA->getState().getKnown());10480    return false;10481  }10482 10483  const std::string getAsStr(Attributor *A) const override {10484    std::string Result = "nofpclass";10485    raw_string_ostream OS(Result);10486    OS << getKnownNoFPClass() << '/' << getAssumedNoFPClass();10487    return Result;10488  }10489 10490  void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,10491                            SmallVectorImpl<Attribute> &Attrs) const override {10492    Attrs.emplace_back(Attribute::getWithNoFPClass(Ctx, getAssumedNoFPClass()));10493  }10494};10495 10496struct AANoFPClassFloating : public AANoFPClassImpl {10497  AANoFPClassFloating(const IRPosition &IRP, Attributor &A)10498      : AANoFPClassImpl(IRP, A) {}10499 10500  /// See AbstractAttribute::updateImpl(...).10501  ChangeStatus updateImpl(Attributor &A) override {10502    SmallVector<AA::ValueAndContext> Values;10503    bool UsedAssumedInformation = false;10504    if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,10505                                      AA::AnyScope, UsedAssumedInformation)) {10506      Values.push_back({getAssociatedValue(), getCtxI()});10507    }10508 10509    StateType T;10510    auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {10511      const auto *AA = A.getAAFor<AANoFPClass>(*this, IRPosition::value(V),10512                                               DepClassTy::REQUIRED);10513      if (!AA || this == AA) {10514        T.indicatePessimisticFixpoint();10515      } else {10516        const AANoFPClass::StateType &S =10517            static_cast<const AANoFPClass::StateType &>(AA->getState());10518        T ^= S;10519      }10520      return T.isValidState();10521    };10522 10523    for (const auto &VAC : Values)10524      if (!VisitValueCB(*VAC.getValue(), VAC.getCtxI()))10525        return indicatePessimisticFixpoint();10526 10527    return clampStateAndIndicateChange(getState(), T);10528  }10529 10530  /// See AbstractAttribute::trackStatistics()10531  void trackStatistics() const override {10532    STATS_DECLTRACK_FNRET_ATTR(nofpclass)10533  }10534};10535 10536struct AANoFPClassReturned final10537    : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,10538                                   AANoFPClassImpl::StateType, false,10539                                   Attribute::None, false> {10540  AANoFPClassReturned(const IRPosition &IRP, Attributor &A)10541      : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,10542                                     AANoFPClassImpl::StateType, false,10543                                     Attribute::None, false>(IRP, A) {}10544 10545  /// See AbstractAttribute::trackStatistics()10546  void trackStatistics() const override {10547    STATS_DECLTRACK_FNRET_ATTR(nofpclass)10548  }10549};10550 10551struct AANoFPClassArgument final10552    : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl> {10553  AANoFPClassArgument(const IRPosition &IRP, Attributor &A)10554      : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl>(IRP, A) {}10555 10556  /// See AbstractAttribute::trackStatistics()10557  void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nofpclass) }10558};10559 10560struct AANoFPClassCallSiteArgument final : AANoFPClassFloating {10561  AANoFPClassCallSiteArgument(const IRPosition &IRP, Attributor &A)10562      : AANoFPClassFloating(IRP, A) {}10563 10564  /// See AbstractAttribute::trackStatistics()10565  void trackStatistics() const override {10566    STATS_DECLTRACK_CSARG_ATTR(nofpclass)10567  }10568};10569 10570struct AANoFPClassCallSiteReturned final10571    : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl> {10572  AANoFPClassCallSiteReturned(const IRPosition &IRP, Attributor &A)10573      : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl>(IRP, A) {}10574 10575  /// See AbstractAttribute::trackStatistics()10576  void trackStatistics() const override {10577    STATS_DECLTRACK_CSRET_ATTR(nofpclass)10578  }10579};10580 10581struct AACallEdgesImpl : public AACallEdges {10582  AACallEdgesImpl(const IRPosition &IRP, Attributor &A) : AACallEdges(IRP, A) {}10583 10584  const SetVector<Function *> &getOptimisticEdges() const override {10585    return CalledFunctions;10586  }10587 10588  bool hasUnknownCallee() const override { return HasUnknownCallee; }10589 10590  bool hasNonAsmUnknownCallee() const override {10591    return HasUnknownCalleeNonAsm;10592  }10593 10594  const std::string getAsStr(Attributor *A) const override {10595    return "CallEdges[" + std::to_string(HasUnknownCallee) + "," +10596           std::to_string(CalledFunctions.size()) + "]";10597  }10598 10599  void trackStatistics() const override {}10600 10601protected:10602  void addCalledFunction(Function *Fn, ChangeStatus &Change) {10603    if (CalledFunctions.insert(Fn)) {10604      Change = ChangeStatus::CHANGED;10605      LLVM_DEBUG(dbgs() << "[AACallEdges] New call edge: " << Fn->getName()10606                        << "\n");10607    }10608  }10609 10610  void setHasUnknownCallee(bool NonAsm, ChangeStatus &Change) {10611    if (!HasUnknownCallee)10612      Change = ChangeStatus::CHANGED;10613    if (NonAsm && !HasUnknownCalleeNonAsm)10614      Change = ChangeStatus::CHANGED;10615    HasUnknownCalleeNonAsm |= NonAsm;10616    HasUnknownCallee = true;10617  }10618 10619private:10620  /// Optimistic set of functions that might be called by this position.10621  SetVector<Function *> CalledFunctions;10622 10623  /// Is there any call with a unknown callee.10624  bool HasUnknownCallee = false;10625 10626  /// Is there any call with a unknown callee, excluding any inline asm.10627  bool HasUnknownCalleeNonAsm = false;10628};10629 10630struct AACallEdgesCallSite : public AACallEdgesImpl {10631  AACallEdgesCallSite(const IRPosition &IRP, Attributor &A)10632      : AACallEdgesImpl(IRP, A) {}10633  /// See AbstractAttribute::updateImpl(...).10634  ChangeStatus updateImpl(Attributor &A) override {10635    ChangeStatus Change = ChangeStatus::UNCHANGED;10636 10637    auto VisitValue = [&](Value &V, const Instruction *CtxI) -> bool {10638      if (Function *Fn = dyn_cast<Function>(&V)) {10639        addCalledFunction(Fn, Change);10640      } else {10641        LLVM_DEBUG(dbgs() << "[AACallEdges] Unrecognized value: " << V << "\n");10642        setHasUnknownCallee(true, Change);10643      }10644 10645      // Explore all values.10646      return true;10647    };10648 10649    SmallVector<AA::ValueAndContext> Values;10650    // Process any value that we might call.10651    auto ProcessCalledOperand = [&](Value *V, Instruction *CtxI) {10652      if (isa<Constant>(V)) {10653        VisitValue(*V, CtxI);10654        return;10655      }10656 10657      bool UsedAssumedInformation = false;10658      Values.clear();10659      if (!A.getAssumedSimplifiedValues(IRPosition::value(*V), *this, Values,10660                                        AA::AnyScope, UsedAssumedInformation)) {10661        Values.push_back({*V, CtxI});10662      }10663      for (auto &VAC : Values)10664        VisitValue(*VAC.getValue(), VAC.getCtxI());10665    };10666 10667    CallBase *CB = cast<CallBase>(getCtxI());10668 10669    if (auto *IA = dyn_cast<InlineAsm>(CB->getCalledOperand())) {10670      if (IA->hasSideEffects() &&10671          !hasAssumption(*CB->getCaller(), "ompx_no_call_asm") &&10672          !hasAssumption(*CB, "ompx_no_call_asm")) {10673        setHasUnknownCallee(false, Change);10674      }10675      return Change;10676    }10677 10678    if (CB->isIndirectCall())10679      if (auto *IndirectCallAA = A.getAAFor<AAIndirectCallInfo>(10680              *this, getIRPosition(), DepClassTy::OPTIONAL))10681        if (IndirectCallAA->foreachCallee(10682                [&](Function *Fn) { return VisitValue(*Fn, CB); }))10683          return Change;10684 10685    // The most simple case.10686    ProcessCalledOperand(CB->getCalledOperand(), CB);10687 10688    // Process callback functions.10689    SmallVector<const Use *, 4u> CallbackUses;10690    AbstractCallSite::getCallbackUses(*CB, CallbackUses);10691    for (const Use *U : CallbackUses)10692      ProcessCalledOperand(U->get(), CB);10693 10694    return Change;10695  }10696};10697 10698struct AACallEdgesFunction : public AACallEdgesImpl {10699  AACallEdgesFunction(const IRPosition &IRP, Attributor &A)10700      : AACallEdgesImpl(IRP, A) {}10701 10702  /// See AbstractAttribute::updateImpl(...).10703  ChangeStatus updateImpl(Attributor &A) override {10704    ChangeStatus Change = ChangeStatus::UNCHANGED;10705 10706    auto ProcessCallInst = [&](Instruction &Inst) {10707      CallBase &CB = cast<CallBase>(Inst);10708 10709      auto *CBEdges = A.getAAFor<AACallEdges>(10710          *this, IRPosition::callsite_function(CB), DepClassTy::REQUIRED);10711      if (!CBEdges)10712        return false;10713      if (CBEdges->hasNonAsmUnknownCallee())10714        setHasUnknownCallee(true, Change);10715      if (CBEdges->hasUnknownCallee())10716        setHasUnknownCallee(false, Change);10717 10718      for (Function *F : CBEdges->getOptimisticEdges())10719        addCalledFunction(F, Change);10720 10721      return true;10722    };10723 10724    // Visit all callable instructions.10725    bool UsedAssumedInformation = false;10726    if (!A.checkForAllCallLikeInstructions(ProcessCallInst, *this,10727                                           UsedAssumedInformation,10728                                           /* CheckBBLivenessOnly */ true)) {10729      // If we haven't looked at all call like instructions, assume that there10730      // are unknown callees.10731      setHasUnknownCallee(true, Change);10732    }10733 10734    return Change;10735  }10736};10737 10738/// -------------------AAInterFnReachability Attribute--------------------------10739 10740struct AAInterFnReachabilityFunction10741    : public CachedReachabilityAA<AAInterFnReachability, Function> {10742  using Base = CachedReachabilityAA<AAInterFnReachability, Function>;10743  AAInterFnReachabilityFunction(const IRPosition &IRP, Attributor &A)10744      : Base(IRP, A) {}10745 10746  bool instructionCanReach(10747      Attributor &A, const Instruction &From, const Function &To,10748      const AA::InstExclusionSetTy *ExclusionSet) const override {10749    assert(From.getFunction() == getAnchorScope() && "Queried the wrong AA!");10750    auto *NonConstThis = const_cast<AAInterFnReachabilityFunction *>(this);10751 10752    RQITy StackRQI(A, From, To, ExclusionSet, false);10753    RQITy::Reachable Result;10754    if (!NonConstThis->checkQueryCache(A, StackRQI, Result))10755      return NonConstThis->isReachableImpl(A, StackRQI,10756                                           /*IsTemporaryRQI=*/true);10757    return Result == RQITy::Reachable::Yes;10758  }10759 10760  bool isReachableImpl(Attributor &A, RQITy &RQI,10761                       bool IsTemporaryRQI) override {10762    const Instruction *EntryI =10763        &RQI.From->getFunction()->getEntryBlock().front();10764    if (EntryI != RQI.From &&10765        !instructionCanReach(A, *EntryI, *RQI.To, nullptr))10766      return rememberResult(A, RQITy::Reachable::No, RQI, false,10767                            IsTemporaryRQI);10768 10769    auto CheckReachableCallBase = [&](CallBase *CB) {10770      auto *CBEdges = A.getAAFor<AACallEdges>(10771          *this, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL);10772      if (!CBEdges || !CBEdges->getState().isValidState())10773        return false;10774      // TODO Check To backwards in this case.10775      if (CBEdges->hasUnknownCallee())10776        return false;10777 10778      for (Function *Fn : CBEdges->getOptimisticEdges()) {10779        if (Fn == RQI.To)10780          return false;10781 10782        if (Fn->isDeclaration()) {10783          if (Fn->hasFnAttribute(Attribute::NoCallback))10784            continue;10785          // TODO Check To backwards in this case.10786          return false;10787        }10788 10789        if (Fn == getAnchorScope()) {10790          if (EntryI == RQI.From)10791            continue;10792          return false;10793        }10794 10795        const AAInterFnReachability *InterFnReachability =10796            A.getAAFor<AAInterFnReachability>(*this, IRPosition::function(*Fn),10797                                              DepClassTy::OPTIONAL);10798 10799        const Instruction &FnFirstInst = Fn->getEntryBlock().front();10800        if (!InterFnReachability ||10801            InterFnReachability->instructionCanReach(A, FnFirstInst, *RQI.To,10802                                                     RQI.ExclusionSet))10803          return false;10804      }10805      return true;10806    };10807 10808    const auto *IntraFnReachability = A.getAAFor<AAIntraFnReachability>(10809        *this, IRPosition::function(*RQI.From->getFunction()),10810        DepClassTy::OPTIONAL);10811 10812    // Determine call like instructions that we can reach from the inst.10813    auto CheckCallBase = [&](Instruction &CBInst) {10814      // There are usually less nodes in the call graph, check inter function10815      // reachability first.10816      if (CheckReachableCallBase(cast<CallBase>(&CBInst)))10817        return true;10818      return IntraFnReachability && !IntraFnReachability->isAssumedReachable(10819                                        A, *RQI.From, CBInst, RQI.ExclusionSet);10820    };10821 10822    bool UsedExclusionSet = /* conservative */ true;10823    bool UsedAssumedInformation = false;10824    if (!A.checkForAllCallLikeInstructions(CheckCallBase, *this,10825                                           UsedAssumedInformation,10826                                           /* CheckBBLivenessOnly */ true))10827      return rememberResult(A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,10828                            IsTemporaryRQI);10829 10830    return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet,10831                          IsTemporaryRQI);10832  }10833 10834  void trackStatistics() const override {}10835};10836} // namespace10837 10838template <typename AAType>10839static std::optional<Constant *>10840askForAssumedConstant(Attributor &A, const AbstractAttribute &QueryingAA,10841                      const IRPosition &IRP, Type &Ty) {10842  if (!Ty.isIntegerTy())10843    return nullptr;10844 10845  // This will also pass the call base context.10846  const auto *AA = A.getAAFor<AAType>(QueryingAA, IRP, DepClassTy::NONE);10847  if (!AA)10848    return nullptr;10849 10850  std::optional<Constant *> COpt = AA->getAssumedConstant(A);10851 10852  if (!COpt.has_value()) {10853    A.recordDependence(*AA, QueryingAA, DepClassTy::OPTIONAL);10854    return std::nullopt;10855  }10856  if (auto *C = *COpt) {10857    A.recordDependence(*AA, QueryingAA, DepClassTy::OPTIONAL);10858    return C;10859  }10860  return nullptr;10861}10862 10863Value *AAPotentialValues::getSingleValue(10864    Attributor &A, const AbstractAttribute &AA, const IRPosition &IRP,10865    SmallVectorImpl<AA::ValueAndContext> &Values) {10866  Type &Ty = *IRP.getAssociatedType();10867  std::optional<Value *> V;10868  for (auto &It : Values) {10869    V = AA::combineOptionalValuesInAAValueLatice(V, It.getValue(), &Ty);10870    if (V.has_value() && !*V)10871      break;10872  }10873  if (!V.has_value())10874    return UndefValue::get(&Ty);10875  return *V;10876}10877 10878namespace {10879struct AAPotentialValuesImpl : AAPotentialValues {10880  using StateType = PotentialLLVMValuesState;10881 10882  AAPotentialValuesImpl(const IRPosition &IRP, Attributor &A)10883      : AAPotentialValues(IRP, A) {}10884 10885  /// See AbstractAttribute::initialize(..).10886  void initialize(Attributor &A) override {10887    if (A.hasSimplificationCallback(getIRPosition())) {10888      indicatePessimisticFixpoint();10889      return;10890    }10891    Value *Stripped = getAssociatedValue().stripPointerCasts();10892    if (isa<Constant>(Stripped) && !isa<ConstantExpr>(Stripped)) {10893      addValue(A, getState(), *Stripped, getCtxI(), AA::AnyScope,10894               getAnchorScope());10895      indicateOptimisticFixpoint();10896      return;10897    }10898    AAPotentialValues::initialize(A);10899  }10900 10901  /// See AbstractAttribute::getAsStr().10902  const std::string getAsStr(Attributor *A) const override {10903    std::string Str;10904    llvm::raw_string_ostream OS(Str);10905    OS << getState();10906    return Str;10907  }10908 10909  template <typename AAType>10910  static std::optional<Value *> askOtherAA(Attributor &A,10911                                           const AbstractAttribute &AA,10912                                           const IRPosition &IRP, Type &Ty) {10913    if (isa<Constant>(IRP.getAssociatedValue()))10914      return &IRP.getAssociatedValue();10915    std::optional<Constant *> C = askForAssumedConstant<AAType>(A, AA, IRP, Ty);10916    if (!C)10917      return std::nullopt;10918    if (*C)10919      if (auto *CC = AA::getWithType(**C, Ty))10920        return CC;10921    return nullptr;10922  }10923 10924  virtual void addValue(Attributor &A, StateType &State, Value &V,10925                        const Instruction *CtxI, AA::ValueScope S,10926                        Function *AnchorScope) const {10927 10928    IRPosition ValIRP = IRPosition::value(V);10929    if (auto *CB = dyn_cast_or_null<CallBase>(CtxI)) {10930      for (const auto &U : CB->args()) {10931        if (U.get() != &V)10932          continue;10933        ValIRP = IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U));10934        break;10935      }10936    }10937 10938    Value *VPtr = &V;10939    if (ValIRP.getAssociatedType()->isIntegerTy()) {10940      Type &Ty = *getAssociatedType();10941      std::optional<Value *> SimpleV =10942          askOtherAA<AAValueConstantRange>(A, *this, ValIRP, Ty);10943      if (SimpleV.has_value() && !*SimpleV) {10944        auto *PotentialConstantsAA = A.getAAFor<AAPotentialConstantValues>(10945            *this, ValIRP, DepClassTy::OPTIONAL);10946        if (PotentialConstantsAA && PotentialConstantsAA->isValidState()) {10947          for (const auto &It : PotentialConstantsAA->getAssumedSet())10948            State.unionAssumed({{*ConstantInt::get(&Ty, It), nullptr}, S});10949          if (PotentialConstantsAA->undefIsContained())10950            State.unionAssumed({{*UndefValue::get(&Ty), nullptr}, S});10951          return;10952        }10953      }10954      if (!SimpleV.has_value())10955        return;10956 10957      if (*SimpleV)10958        VPtr = *SimpleV;10959    }10960 10961    if (isa<ConstantInt>(VPtr))10962      CtxI = nullptr;10963    if (!AA::isValidInScope(*VPtr, AnchorScope))10964      S = AA::ValueScope(S | AA::Interprocedural);10965 10966    State.unionAssumed({{*VPtr, CtxI}, S});10967  }10968 10969  /// Helper struct to tie a value+context pair together with the scope for10970  /// which this is the simplified version.10971  struct ItemInfo {10972    AA::ValueAndContext I;10973    AA::ValueScope S;10974 10975    bool operator==(const ItemInfo &II) const {10976      return II.I == I && II.S == S;10977    };10978    bool operator<(const ItemInfo &II) const {10979      return std::tie(I, S) < std::tie(II.I, II.S);10980    };10981  };10982 10983  bool recurseForValue(Attributor &A, const IRPosition &IRP, AA::ValueScope S) {10984    SmallMapVector<AA::ValueAndContext, int, 8> ValueScopeMap;10985    for (auto CS : {AA::Intraprocedural, AA::Interprocedural}) {10986      if (!(CS & S))10987        continue;10988 10989      bool UsedAssumedInformation = false;10990      SmallVector<AA::ValueAndContext> Values;10991      if (!A.getAssumedSimplifiedValues(IRP, this, Values, CS,10992                                        UsedAssumedInformation))10993        return false;10994 10995      for (auto &It : Values)10996        ValueScopeMap[It] += CS;10997    }10998    for (auto &It : ValueScopeMap)10999      addValue(A, getState(), *It.first.getValue(), It.first.getCtxI(),11000               AA::ValueScope(It.second), getAnchorScope());11001 11002    return true;11003  }11004 11005  void giveUpOnIntraprocedural(Attributor &A) {11006    auto NewS = StateType::getBestState(getState());11007    for (const auto &It : getAssumedSet()) {11008      if (It.second == AA::Intraprocedural)11009        continue;11010      addValue(A, NewS, *It.first.getValue(), It.first.getCtxI(),11011               AA::Interprocedural, getAnchorScope());11012    }11013    assert(!undefIsContained() && "Undef should be an explicit value!");11014    addValue(A, NewS, getAssociatedValue(), getCtxI(), AA::Intraprocedural,11015             getAnchorScope());11016    getState() = NewS;11017  }11018 11019  /// See AbstractState::indicatePessimisticFixpoint(...).11020  ChangeStatus indicatePessimisticFixpoint() override {11021    getState() = StateType::getBestState(getState());11022    getState().unionAssumed({{getAssociatedValue(), getCtxI()}, AA::AnyScope});11023    AAPotentialValues::indicateOptimisticFixpoint();11024    return ChangeStatus::CHANGED;11025  }11026 11027  /// See AbstractAttribute::updateImpl(...).11028  ChangeStatus updateImpl(Attributor &A) override {11029    return indicatePessimisticFixpoint();11030  }11031 11032  /// See AbstractAttribute::manifest(...).11033  ChangeStatus manifest(Attributor &A) override {11034    SmallVector<AA::ValueAndContext> Values;11035    for (AA::ValueScope S : {AA::Interprocedural, AA::Intraprocedural}) {11036      Values.clear();11037      if (!getAssumedSimplifiedValues(A, Values, S))11038        continue;11039      Value &OldV = getAssociatedValue();11040      if (isa<UndefValue>(OldV))11041        continue;11042      Value *NewV = getSingleValue(A, *this, getIRPosition(), Values);11043      if (!NewV || NewV == &OldV)11044        continue;11045      if (getCtxI() &&11046          !AA::isValidAtPosition({*NewV, *getCtxI()}, A.getInfoCache()))11047        continue;11048      if (A.changeAfterManifest(getIRPosition(), *NewV))11049        return ChangeStatus::CHANGED;11050    }11051    return ChangeStatus::UNCHANGED;11052  }11053 11054  bool getAssumedSimplifiedValues(11055      Attributor &A, SmallVectorImpl<AA::ValueAndContext> &Values,11056      AA::ValueScope S, bool RecurseForSelectAndPHI = false) const override {11057    if (!isValidState())11058      return false;11059    bool UsedAssumedInformation = false;11060    for (const auto &It : getAssumedSet())11061      if (It.second & S) {11062        if (RecurseForSelectAndPHI && (isa<PHINode>(It.first.getValue()) ||11063                                       isa<SelectInst>(It.first.getValue()))) {11064          if (A.getAssumedSimplifiedValues(11065                  IRPosition::inst(*cast<Instruction>(It.first.getValue())),11066                  this, Values, S, UsedAssumedInformation))11067            continue;11068        }11069        Values.push_back(It.first);11070      }11071    assert(!undefIsContained() && "Undef should be an explicit value!");11072    return true;11073  }11074};11075 11076struct AAPotentialValuesFloating : AAPotentialValuesImpl {11077  AAPotentialValuesFloating(const IRPosition &IRP, Attributor &A)11078      : AAPotentialValuesImpl(IRP, A) {}11079 11080  /// See AbstractAttribute::updateImpl(...).11081  ChangeStatus updateImpl(Attributor &A) override {11082    auto AssumedBefore = getAssumed();11083 11084    genericValueTraversal(A, &getAssociatedValue());11085 11086    return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED11087                                           : ChangeStatus::CHANGED;11088  }11089 11090  /// Helper struct to remember which AAIsDead instances we actually used.11091  struct LivenessInfo {11092    const AAIsDead *LivenessAA = nullptr;11093    bool AnyDead = false;11094  };11095 11096  /// Check if \p Cmp is a comparison we can simplify.11097  ///11098  /// We handle multiple cases, one in which at least one operand is an11099  /// (assumed) nullptr. If so, try to simplify it using AANonNull on the other11100  /// operand. Return true if successful, in that case Worklist will be updated.11101  bool handleCmp(Attributor &A, Value &Cmp, Value *LHS, Value *RHS,11102                 CmpInst::Predicate Pred, ItemInfo II,11103                 SmallVectorImpl<ItemInfo> &Worklist) {11104 11105    // Simplify the operands first.11106    bool UsedAssumedInformation = false;11107    SmallVector<AA::ValueAndContext> LHSValues, RHSValues;11108    auto GetSimplifiedValues = [&](Value &V,11109                                   SmallVector<AA::ValueAndContext> &Values) {11110      if (!A.getAssumedSimplifiedValues(11111              IRPosition::value(V, getCallBaseContext()), this, Values,11112              AA::Intraprocedural, UsedAssumedInformation)) {11113        Values.clear();11114        Values.push_back(AA::ValueAndContext{V, II.I.getCtxI()});11115      }11116      return Values.empty();11117    };11118    if (GetSimplifiedValues(*LHS, LHSValues))11119      return true;11120    if (GetSimplifiedValues(*RHS, RHSValues))11121      return true;11122 11123    LLVMContext &Ctx = LHS->getContext();11124 11125    InformationCache &InfoCache = A.getInfoCache();11126    Instruction *CmpI = dyn_cast<Instruction>(&Cmp);11127    Function *F = CmpI ? CmpI->getFunction() : nullptr;11128    const auto *DT =11129        F ? InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F)11130          : nullptr;11131    const auto *TLI =11132        F ? A.getInfoCache().getTargetLibraryInfoForFunction(*F) : nullptr;11133    auto *AC =11134        F ? InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F)11135          : nullptr;11136 11137    const DataLayout &DL = A.getDataLayout();11138    SimplifyQuery Q(DL, TLI, DT, AC, CmpI);11139 11140    auto CheckPair = [&](Value &LHSV, Value &RHSV) {11141      if (isa<UndefValue>(LHSV) || isa<UndefValue>(RHSV)) {11142        addValue(A, getState(), *UndefValue::get(Cmp.getType()),11143                 /* CtxI */ nullptr, II.S, getAnchorScope());11144        return true;11145      }11146 11147      // Handle the trivial case first in which we don't even need to think11148      // about null or non-null.11149      if (&LHSV == &RHSV &&11150          (CmpInst::isTrueWhenEqual(Pred) || CmpInst::isFalseWhenEqual(Pred))) {11151        Constant *NewV = ConstantInt::get(Type::getInt1Ty(Ctx),11152                                          CmpInst::isTrueWhenEqual(Pred));11153        addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S,11154                 getAnchorScope());11155        return true;11156      }11157 11158      auto *TypedLHS = AA::getWithType(LHSV, *LHS->getType());11159      auto *TypedRHS = AA::getWithType(RHSV, *RHS->getType());11160      if (TypedLHS && TypedRHS) {11161        Value *NewV = simplifyCmpInst(Pred, TypedLHS, TypedRHS, Q);11162        if (NewV && NewV != &Cmp) {11163          addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S,11164                   getAnchorScope());11165          return true;11166        }11167      }11168 11169      // From now on we only handle equalities (==, !=).11170      if (!CmpInst::isEquality(Pred))11171        return false;11172 11173      bool LHSIsNull = isa<ConstantPointerNull>(LHSV);11174      bool RHSIsNull = isa<ConstantPointerNull>(RHSV);11175      if (!LHSIsNull && !RHSIsNull)11176        return false;11177 11178      // Left is the nullptr ==/!= non-nullptr case. We'll use AANonNull on the11179      // non-nullptr operand and if we assume it's non-null we can conclude the11180      // result of the comparison.11181      assert((LHSIsNull || RHSIsNull) &&11182             "Expected nullptr versus non-nullptr comparison at this point");11183 11184      // The index is the operand that we assume is not null.11185      unsigned PtrIdx = LHSIsNull;11186      bool IsKnownNonNull;11187      bool IsAssumedNonNull = AA::hasAssumedIRAttr<Attribute::NonNull>(11188          A, this, IRPosition::value(*(PtrIdx ? &RHSV : &LHSV)),11189          DepClassTy::REQUIRED, IsKnownNonNull);11190      if (!IsAssumedNonNull)11191        return false;11192 11193      // The new value depends on the predicate, true for != and false for ==.11194      Constant *NewV =11195          ConstantInt::get(Type::getInt1Ty(Ctx), Pred == CmpInst::ICMP_NE);11196      addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S,11197               getAnchorScope());11198      return true;11199    };11200 11201    for (auto &LHSValue : LHSValues)11202      for (auto &RHSValue : RHSValues)11203        if (!CheckPair(*LHSValue.getValue(), *RHSValue.getValue()))11204          return false;11205    return true;11206  }11207 11208  bool handleSelectInst(Attributor &A, SelectInst &SI, ItemInfo II,11209                        SmallVectorImpl<ItemInfo> &Worklist) {11210    const Instruction *CtxI = II.I.getCtxI();11211    bool UsedAssumedInformation = false;11212 11213    std::optional<Constant *> C =11214        A.getAssumedConstant(*SI.getCondition(), *this, UsedAssumedInformation);11215    bool NoValueYet = !C.has_value();11216    if (NoValueYet || isa_and_nonnull<UndefValue>(*C))11217      return true;11218    if (auto *CI = dyn_cast_or_null<ConstantInt>(*C)) {11219      if (CI->isZero())11220        Worklist.push_back({{*SI.getFalseValue(), CtxI}, II.S});11221      else11222        Worklist.push_back({{*SI.getTrueValue(), CtxI}, II.S});11223    } else if (&SI == &getAssociatedValue()) {11224      // We could not simplify the condition, assume both values.11225      Worklist.push_back({{*SI.getTrueValue(), CtxI}, II.S});11226      Worklist.push_back({{*SI.getFalseValue(), CtxI}, II.S});11227    } else {11228      std::optional<Value *> SimpleV = A.getAssumedSimplified(11229          IRPosition::inst(SI), *this, UsedAssumedInformation, II.S);11230      if (!SimpleV.has_value())11231        return true;11232      if (*SimpleV) {11233        addValue(A, getState(), **SimpleV, CtxI, II.S, getAnchorScope());11234        return true;11235      }11236      return false;11237    }11238    return true;11239  }11240 11241  bool handleLoadInst(Attributor &A, LoadInst &LI, ItemInfo II,11242                      SmallVectorImpl<ItemInfo> &Worklist) {11243    SmallSetVector<Value *, 4> PotentialCopies;11244    SmallSetVector<Instruction *, 4> PotentialValueOrigins;11245    bool UsedAssumedInformation = false;11246    if (!AA::getPotentiallyLoadedValues(A, LI, PotentialCopies,11247                                        PotentialValueOrigins, *this,11248                                        UsedAssumedInformation,11249                                        /* OnlyExact */ true)) {11250      LLVM_DEBUG(dbgs() << "[AAPotentialValues] Failed to get potentially "11251                           "loaded values for load instruction "11252                        << LI << "\n");11253      return false;11254    }11255 11256    // Do not simplify loads that are only used in llvm.assume if we cannot also11257    // remove all stores that may feed into the load. The reason is that the11258    // assume is probably worth something as long as the stores are around.11259    InformationCache &InfoCache = A.getInfoCache();11260    if (InfoCache.isOnlyUsedByAssume(LI)) {11261      if (!llvm::all_of(PotentialValueOrigins, [&](Instruction *I) {11262            if (!I || isa<AssumeInst>(I))11263              return true;11264            if (auto *SI = dyn_cast<StoreInst>(I))11265              return A.isAssumedDead(SI->getOperandUse(0), this,11266                                     /* LivenessAA */ nullptr,11267                                     UsedAssumedInformation,11268                                     /* CheckBBLivenessOnly */ false);11269            return A.isAssumedDead(*I, this, /* LivenessAA */ nullptr,11270                                   UsedAssumedInformation,11271                                   /* CheckBBLivenessOnly */ false);11272          })) {11273        LLVM_DEBUG(dbgs() << "[AAPotentialValues] Load is onl used by assumes "11274                             "and we cannot delete all the stores: "11275                          << LI << "\n");11276        return false;11277      }11278    }11279 11280    // Values have to be dynamically unique or we loose the fact that a11281    // single llvm::Value might represent two runtime values (e.g.,11282    // stack locations in different recursive calls).11283    const Instruction *CtxI = II.I.getCtxI();11284    bool ScopeIsLocal = (II.S & AA::Intraprocedural);11285    bool AllLocal = ScopeIsLocal;11286    bool DynamicallyUnique = llvm::all_of(PotentialCopies, [&](Value *PC) {11287      AllLocal &= AA::isValidInScope(*PC, getAnchorScope());11288      return AA::isDynamicallyUnique(A, *this, *PC);11289    });11290    if (!DynamicallyUnique) {11291      LLVM_DEBUG(dbgs() << "[AAPotentialValues] Not all potentially loaded "11292                           "values are dynamically unique: "11293                        << LI << "\n");11294      return false;11295    }11296 11297    for (auto *PotentialCopy : PotentialCopies) {11298      if (AllLocal) {11299        Worklist.push_back({{*PotentialCopy, CtxI}, II.S});11300      } else {11301        Worklist.push_back({{*PotentialCopy, CtxI}, AA::Interprocedural});11302      }11303    }11304    if (!AllLocal && ScopeIsLocal)11305      addValue(A, getState(), LI, CtxI, AA::Intraprocedural, getAnchorScope());11306    return true;11307  }11308 11309  bool handlePHINode(11310      Attributor &A, PHINode &PHI, ItemInfo II,11311      SmallVectorImpl<ItemInfo> &Worklist,11312      SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {11313    auto GetLivenessInfo = [&](const Function &F) -> LivenessInfo & {11314      LivenessInfo &LI = LivenessAAs[&F];11315      if (!LI.LivenessAA)11316        LI.LivenessAA = A.getAAFor<AAIsDead>(*this, IRPosition::function(F),11317                                             DepClassTy::NONE);11318      return LI;11319    };11320 11321    if (&PHI == &getAssociatedValue()) {11322      LivenessInfo &LI = GetLivenessInfo(*PHI.getFunction());11323      const auto *CI =11324          A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(11325              *PHI.getFunction());11326 11327      Cycle *C = nullptr;11328      bool CyclePHI = mayBeInCycle(CI, &PHI, /* HeaderOnly */ true, &C);11329      for (unsigned u = 0, e = PHI.getNumIncomingValues(); u < e; u++) {11330        BasicBlock *IncomingBB = PHI.getIncomingBlock(u);11331        if (LI.LivenessAA &&11332            LI.LivenessAA->isEdgeDead(IncomingBB, PHI.getParent())) {11333          LI.AnyDead = true;11334          continue;11335        }11336        Value *V = PHI.getIncomingValue(u);11337        if (V == &PHI)11338          continue;11339 11340        // If the incoming value is not the PHI but an instruction in the same11341        // cycle we might have multiple versions of it flying around.11342        if (CyclePHI && isa<Instruction>(V) &&11343            (!C || C->contains(cast<Instruction>(V)->getParent())))11344          return false;11345 11346        Worklist.push_back({{*V, IncomingBB->getTerminator()}, II.S});11347      }11348      return true;11349    }11350 11351    bool UsedAssumedInformation = false;11352    std::optional<Value *> SimpleV = A.getAssumedSimplified(11353        IRPosition::inst(PHI), *this, UsedAssumedInformation, II.S);11354    if (!SimpleV.has_value())11355      return true;11356    if (!(*SimpleV))11357      return false;11358    addValue(A, getState(), **SimpleV, &PHI, II.S, getAnchorScope());11359    return true;11360  }11361 11362  /// Use the generic, non-optimistic InstSimplfy functionality if we managed to11363  /// simplify any operand of the instruction \p I. Return true if successful,11364  /// in that case Worklist will be updated.11365  bool handleGenericInst(Attributor &A, Instruction &I, ItemInfo II,11366                         SmallVectorImpl<ItemInfo> &Worklist) {11367    bool SomeSimplified = false;11368    bool UsedAssumedInformation = false;11369 11370    SmallVector<Value *, 8> NewOps(I.getNumOperands());11371    int Idx = 0;11372    for (Value *Op : I.operands()) {11373      const auto &SimplifiedOp = A.getAssumedSimplified(11374          IRPosition::value(*Op, getCallBaseContext()), *this,11375          UsedAssumedInformation, AA::Intraprocedural);11376      // If we are not sure about any operand we are not sure about the entire11377      // instruction, we'll wait.11378      if (!SimplifiedOp.has_value())11379        return true;11380 11381      if (*SimplifiedOp)11382        NewOps[Idx] = *SimplifiedOp;11383      else11384        NewOps[Idx] = Op;11385 11386      SomeSimplified |= (NewOps[Idx] != Op);11387      ++Idx;11388    }11389 11390    // We won't bother with the InstSimplify interface if we didn't simplify any11391    // operand ourselves.11392    if (!SomeSimplified)11393      return false;11394 11395    InformationCache &InfoCache = A.getInfoCache();11396    Function *F = I.getFunction();11397    const auto *DT =11398        InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);11399    const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);11400    auto *AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);11401 11402    const DataLayout &DL = I.getDataLayout();11403    SimplifyQuery Q(DL, TLI, DT, AC, &I);11404    Value *NewV = simplifyInstructionWithOperands(&I, NewOps, Q);11405    if (!NewV || NewV == &I)11406      return false;11407 11408    LLVM_DEBUG(dbgs() << "Generic inst " << I << " assumed simplified to "11409                      << *NewV << "\n");11410    Worklist.push_back({{*NewV, II.I.getCtxI()}, II.S});11411    return true;11412  }11413 11414  bool simplifyInstruction(11415      Attributor &A, Instruction &I, ItemInfo II,11416      SmallVectorImpl<ItemInfo> &Worklist,11417      SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {11418    if (auto *CI = dyn_cast<CmpInst>(&I))11419      return handleCmp(A, *CI, CI->getOperand(0), CI->getOperand(1),11420                       CI->getPredicate(), II, Worklist);11421 11422    switch (I.getOpcode()) {11423    case Instruction::Select:11424      return handleSelectInst(A, cast<SelectInst>(I), II, Worklist);11425    case Instruction::PHI:11426      return handlePHINode(A, cast<PHINode>(I), II, Worklist, LivenessAAs);11427    case Instruction::Load:11428      return handleLoadInst(A, cast<LoadInst>(I), II, Worklist);11429    default:11430      return handleGenericInst(A, I, II, Worklist);11431    };11432    return false;11433  }11434 11435  void genericValueTraversal(Attributor &A, Value *InitialV) {11436    SmallMapVector<const Function *, LivenessInfo, 4> LivenessAAs;11437 11438    SmallSet<ItemInfo, 16> Visited;11439    SmallVector<ItemInfo, 16> Worklist;11440    Worklist.push_back({{*InitialV, getCtxI()}, AA::AnyScope});11441 11442    int Iteration = 0;11443    do {11444      ItemInfo II = Worklist.pop_back_val();11445      Value *V = II.I.getValue();11446      assert(V);11447      const Instruction *CtxI = II.I.getCtxI();11448      AA::ValueScope S = II.S;11449 11450      // Check if we should process the current value. To prevent endless11451      // recursion keep a record of the values we followed!11452      if (!Visited.insert(II).second)11453        continue;11454 11455      // Make sure we limit the compile time for complex expressions.11456      if (Iteration++ >= MaxPotentialValuesIterations) {11457        LLVM_DEBUG(dbgs() << "Generic value traversal reached iteration limit: "11458                          << Iteration << "!\n");11459        addValue(A, getState(), *V, CtxI, S, getAnchorScope());11460        continue;11461      }11462 11463      // Explicitly look through calls with a "returned" attribute if we do11464      // not have a pointer as stripPointerCasts only works on them.11465      Value *NewV = nullptr;11466      if (V->getType()->isPointerTy()) {11467        NewV = AA::getWithType(*V->stripPointerCasts(), *V->getType());11468      } else {11469        if (auto *CB = dyn_cast<CallBase>(V))11470          if (auto *Callee =11471                  dyn_cast_if_present<Function>(CB->getCalledOperand())) {11472            for (Argument &Arg : Callee->args())11473              if (Arg.hasReturnedAttr()) {11474                NewV = CB->getArgOperand(Arg.getArgNo());11475                break;11476              }11477          }11478      }11479      if (NewV && NewV != V) {11480        Worklist.push_back({{*NewV, CtxI}, S});11481        continue;11482      }11483 11484      if (auto *I = dyn_cast<Instruction>(V)) {11485        if (simplifyInstruction(A, *I, II, Worklist, LivenessAAs))11486          continue;11487      }11488 11489      if (V != InitialV || isa<Argument>(V))11490        if (recurseForValue(A, IRPosition::value(*V), II.S))11491          continue;11492 11493      // If we haven't stripped anything we give up.11494      if (V == InitialV && CtxI == getCtxI()) {11495        indicatePessimisticFixpoint();11496        return;11497      }11498 11499      addValue(A, getState(), *V, CtxI, S, getAnchorScope());11500    } while (!Worklist.empty());11501 11502    // If we actually used liveness information so we have to record a11503    // dependence.11504    for (auto &It : LivenessAAs)11505      if (It.second.AnyDead)11506        A.recordDependence(*It.second.LivenessAA, *this, DepClassTy::OPTIONAL);11507  }11508 11509  /// See AbstractAttribute::trackStatistics()11510  void trackStatistics() const override {11511    STATS_DECLTRACK_FLOATING_ATTR(potential_values)11512  }11513};11514 11515struct AAPotentialValuesArgument final : AAPotentialValuesImpl {11516  using Base = AAPotentialValuesImpl;11517  AAPotentialValuesArgument(const IRPosition &IRP, Attributor &A)11518      : Base(IRP, A) {}11519 11520  /// See AbstractAttribute::initialize(..).11521  void initialize(Attributor &A) override {11522    auto &Arg = cast<Argument>(getAssociatedValue());11523    if (Arg.hasPointeeInMemoryValueAttr())11524      indicatePessimisticFixpoint();11525  }11526 11527  /// See AbstractAttribute::updateImpl(...).11528  ChangeStatus updateImpl(Attributor &A) override {11529    auto AssumedBefore = getAssumed();11530 11531    unsigned ArgNo = getCalleeArgNo();11532 11533    bool UsedAssumedInformation = false;11534    SmallVector<AA::ValueAndContext> Values;11535    auto CallSitePred = [&](AbstractCallSite ACS) {11536      const auto CSArgIRP = IRPosition::callsite_argument(ACS, ArgNo);11537      if (CSArgIRP.getPositionKind() == IRP_INVALID)11538        return false;11539 11540      if (!A.getAssumedSimplifiedValues(CSArgIRP, this, Values,11541                                        AA::Interprocedural,11542                                        UsedAssumedInformation))11543        return false;11544 11545      return isValidState();11546    };11547 11548    if (!A.checkForAllCallSites(CallSitePred, *this,11549                                /* RequireAllCallSites */ true,11550                                UsedAssumedInformation))11551      return indicatePessimisticFixpoint();11552 11553    Function *Fn = getAssociatedFunction();11554    bool AnyNonLocal = false;11555    for (auto &It : Values) {11556      if (isa<Constant>(It.getValue())) {11557        addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::AnyScope,11558                 getAnchorScope());11559        continue;11560      }11561      if (!AA::isDynamicallyUnique(A, *this, *It.getValue()))11562        return indicatePessimisticFixpoint();11563 11564      if (auto *Arg = dyn_cast<Argument>(It.getValue()))11565        if (Arg->getParent() == Fn) {11566          addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::AnyScope,11567                   getAnchorScope());11568          continue;11569        }11570      addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::Interprocedural,11571               getAnchorScope());11572      AnyNonLocal = true;11573    }11574    assert(!undefIsContained() && "Undef should be an explicit value!");11575    if (AnyNonLocal)11576      giveUpOnIntraprocedural(A);11577 11578    return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED11579                                           : ChangeStatus::CHANGED;11580  }11581 11582  /// See AbstractAttribute::trackStatistics()11583  void trackStatistics() const override {11584    STATS_DECLTRACK_ARG_ATTR(potential_values)11585  }11586};11587 11588struct AAPotentialValuesReturned : public AAPotentialValuesFloating {11589  using Base = AAPotentialValuesFloating;11590  AAPotentialValuesReturned(const IRPosition &IRP, Attributor &A)11591      : Base(IRP, A) {}11592 11593  /// See AbstractAttribute::initialize(..).11594  void initialize(Attributor &A) override {11595    Function *F = getAssociatedFunction();11596    if (!F || F->isDeclaration() || F->getReturnType()->isVoidTy()) {11597      indicatePessimisticFixpoint();11598      return;11599    }11600 11601    for (Argument &Arg : F->args())11602      if (Arg.hasReturnedAttr()) {11603        addValue(A, getState(), Arg, nullptr, AA::AnyScope, F);11604        ReturnedArg = &Arg;11605        break;11606      }11607    if (!A.isFunctionIPOAmendable(*F) ||11608        A.hasSimplificationCallback(getIRPosition())) {11609      if (!ReturnedArg)11610        indicatePessimisticFixpoint();11611      else11612        indicateOptimisticFixpoint();11613    }11614  }11615 11616  /// See AbstractAttribute::updateImpl(...).11617  ChangeStatus updateImpl(Attributor &A) override {11618    auto AssumedBefore = getAssumed();11619    bool UsedAssumedInformation = false;11620 11621    SmallVector<AA::ValueAndContext> Values;11622    Function *AnchorScope = getAnchorScope();11623    auto HandleReturnedValue = [&](Value &V, Instruction *CtxI,11624                                   bool AddValues) {11625      for (AA::ValueScope S : {AA::Interprocedural, AA::Intraprocedural}) {11626        Values.clear();11627        if (!A.getAssumedSimplifiedValues(IRPosition::value(V), this, Values, S,11628                                          UsedAssumedInformation,11629                                          /* RecurseForSelectAndPHI */ true))11630          return false;11631        if (!AddValues)11632          continue;11633 11634        bool AllInterAreIntra = false;11635        if (S == AA::Interprocedural)11636          AllInterAreIntra =11637              llvm::all_of(Values, [&](const AA::ValueAndContext &VAC) {11638                return AA::isValidInScope(*VAC.getValue(), AnchorScope);11639              });11640 11641        for (const AA::ValueAndContext &VAC : Values) {11642          addValue(A, getState(), *VAC.getValue(),11643                   VAC.getCtxI() ? VAC.getCtxI() : CtxI,11644                   AllInterAreIntra ? AA::AnyScope : S, AnchorScope);11645        }11646        if (AllInterAreIntra)11647          break;11648      }11649      return true;11650    };11651 11652    if (ReturnedArg) {11653      HandleReturnedValue(*ReturnedArg, nullptr, true);11654    } else {11655      auto RetInstPred = [&](Instruction &RetI) {11656        bool AddValues = true;11657        if (isa<PHINode>(RetI.getOperand(0)) ||11658            isa<SelectInst>(RetI.getOperand(0))) {11659          addValue(A, getState(), *RetI.getOperand(0), &RetI, AA::AnyScope,11660                   AnchorScope);11661          AddValues = false;11662        }11663        return HandleReturnedValue(*RetI.getOperand(0), &RetI, AddValues);11664      };11665 11666      if (!A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret},11667                                     UsedAssumedInformation,11668                                     /* CheckBBLivenessOnly */ true))11669        return indicatePessimisticFixpoint();11670    }11671 11672    return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED11673                                           : ChangeStatus::CHANGED;11674  }11675 11676  ChangeStatus manifest(Attributor &A) override {11677    if (ReturnedArg)11678      return ChangeStatus::UNCHANGED;11679    SmallVector<AA::ValueAndContext> Values;11680    if (!getAssumedSimplifiedValues(A, Values, AA::ValueScope::Intraprocedural,11681                                    /* RecurseForSelectAndPHI */ true))11682      return ChangeStatus::UNCHANGED;11683    Value *NewVal = getSingleValue(A, *this, getIRPosition(), Values);11684    if (!NewVal)11685      return ChangeStatus::UNCHANGED;11686 11687    ChangeStatus Changed = ChangeStatus::UNCHANGED;11688    if (auto *Arg = dyn_cast<Argument>(NewVal)) {11689      STATS_DECLTRACK(UniqueReturnValue, FunctionReturn,11690                      "Number of function with unique return");11691      Changed |= A.manifestAttrs(11692          IRPosition::argument(*Arg),11693          {Attribute::get(Arg->getContext(), Attribute::Returned)});11694      STATS_DECLTRACK_ARG_ATTR(returned);11695    }11696 11697    auto RetInstPred = [&](Instruction &RetI) {11698      Value *RetOp = RetI.getOperand(0);11699      if (isa<UndefValue>(RetOp) || RetOp == NewVal)11700        return true;11701      if (AA::isValidAtPosition({*NewVal, RetI}, A.getInfoCache()))11702        if (A.changeUseAfterManifest(RetI.getOperandUse(0), *NewVal))11703          Changed = ChangeStatus::CHANGED;11704      return true;11705    };11706    bool UsedAssumedInformation = false;11707    (void)A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret},11708                                    UsedAssumedInformation,11709                                    /* CheckBBLivenessOnly */ true);11710    return Changed;11711  }11712 11713  ChangeStatus indicatePessimisticFixpoint() override {11714    return AAPotentialValues::indicatePessimisticFixpoint();11715  }11716 11717  /// See AbstractAttribute::trackStatistics()11718  void trackStatistics() const override{11719      STATS_DECLTRACK_FNRET_ATTR(potential_values)}11720 11721  /// The argumented with an existing `returned` attribute.11722  Argument *ReturnedArg = nullptr;11723};11724 11725struct AAPotentialValuesFunction : AAPotentialValuesImpl {11726  AAPotentialValuesFunction(const IRPosition &IRP, Attributor &A)11727      : AAPotentialValuesImpl(IRP, A) {}11728 11729  /// See AbstractAttribute::updateImpl(...).11730  ChangeStatus updateImpl(Attributor &A) override {11731    llvm_unreachable("AAPotentialValues(Function|CallSite)::updateImpl will "11732                     "not be called");11733  }11734 11735  /// See AbstractAttribute::trackStatistics()11736  void trackStatistics() const override {11737    STATS_DECLTRACK_FN_ATTR(potential_values)11738  }11739};11740 11741struct AAPotentialValuesCallSite : AAPotentialValuesFunction {11742  AAPotentialValuesCallSite(const IRPosition &IRP, Attributor &A)11743      : AAPotentialValuesFunction(IRP, A) {}11744 11745  /// See AbstractAttribute::trackStatistics()11746  void trackStatistics() const override {11747    STATS_DECLTRACK_CS_ATTR(potential_values)11748  }11749};11750 11751struct AAPotentialValuesCallSiteReturned : AAPotentialValuesImpl {11752  AAPotentialValuesCallSiteReturned(const IRPosition &IRP, Attributor &A)11753      : AAPotentialValuesImpl(IRP, A) {}11754 11755  /// See AbstractAttribute::updateImpl(...).11756  ChangeStatus updateImpl(Attributor &A) override {11757    auto AssumedBefore = getAssumed();11758 11759    Function *Callee = getAssociatedFunction();11760    if (!Callee)11761      return indicatePessimisticFixpoint();11762 11763    bool UsedAssumedInformation = false;11764    auto *CB = cast<CallBase>(getCtxI());11765    if (CB->isMustTailCall() &&11766        !A.isAssumedDead(IRPosition::inst(*CB), this, nullptr,11767                         UsedAssumedInformation))11768      return indicatePessimisticFixpoint();11769 11770    Function *Caller = CB->getCaller();11771 11772    auto AddScope = [&](AA::ValueScope S) {11773      SmallVector<AA::ValueAndContext> Values;11774      if (!A.getAssumedSimplifiedValues(IRPosition::returned(*Callee), this,11775                                        Values, S, UsedAssumedInformation))11776        return false;11777 11778      for (auto &It : Values) {11779        Value *V = It.getValue();11780        std::optional<Value *> CallerV = A.translateArgumentToCallSiteContent(11781            V, *CB, *this, UsedAssumedInformation);11782        if (!CallerV.has_value()) {11783          // Nothing to do as long as no value was determined.11784          continue;11785        }11786        V = *CallerV ? *CallerV : V;11787        if (*CallerV && AA::isDynamicallyUnique(A, *this, *V)) {11788          if (recurseForValue(A, IRPosition::value(*V), S))11789            continue;11790        }11791        if (S == AA::Intraprocedural && !AA::isValidInScope(*V, Caller)) {11792          giveUpOnIntraprocedural(A);11793          return true;11794        }11795        addValue(A, getState(), *V, CB, S, getAnchorScope());11796      }11797      return true;11798    };11799    if (!AddScope(AA::Intraprocedural))11800      return indicatePessimisticFixpoint();11801    if (!AddScope(AA::Interprocedural))11802      return indicatePessimisticFixpoint();11803    return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED11804                                           : ChangeStatus::CHANGED;11805  }11806 11807  ChangeStatus indicatePessimisticFixpoint() override {11808    return AAPotentialValues::indicatePessimisticFixpoint();11809  }11810 11811  /// See AbstractAttribute::trackStatistics()11812  void trackStatistics() const override {11813    STATS_DECLTRACK_CSRET_ATTR(potential_values)11814  }11815};11816 11817struct AAPotentialValuesCallSiteArgument : AAPotentialValuesFloating {11818  AAPotentialValuesCallSiteArgument(const IRPosition &IRP, Attributor &A)11819      : AAPotentialValuesFloating(IRP, A) {}11820 11821  /// See AbstractAttribute::trackStatistics()11822  void trackStatistics() const override {11823    STATS_DECLTRACK_CSARG_ATTR(potential_values)11824  }11825};11826} // namespace11827 11828/// ---------------------- Assumption Propagation ------------------------------11829namespace {11830struct AAAssumptionInfoImpl : public AAAssumptionInfo {11831  AAAssumptionInfoImpl(const IRPosition &IRP, Attributor &A,11832                       const DenseSet<StringRef> &Known)11833      : AAAssumptionInfo(IRP, A, Known) {}11834 11835  /// See AbstractAttribute::manifest(...).11836  ChangeStatus manifest(Attributor &A) override {11837    // Don't manifest a universal set if it somehow made it here.11838    if (getKnown().isUniversal())11839      return ChangeStatus::UNCHANGED;11840 11841    const IRPosition &IRP = getIRPosition();11842    SmallVector<StringRef, 0> Set(getAssumed().getSet().begin(),11843                                  getAssumed().getSet().end());11844    llvm::sort(Set);11845    return A.manifestAttrs(IRP,11846                           Attribute::get(IRP.getAnchorValue().getContext(),11847                                          AssumptionAttrKey,11848                                          llvm::join(Set, ",")),11849                           /*ForceReplace=*/true);11850  }11851 11852  bool hasAssumption(const StringRef Assumption) const override {11853    return isValidState() && setContains(Assumption);11854  }11855 11856  /// See AbstractAttribute::getAsStr()11857  const std::string getAsStr(Attributor *A) const override {11858    const SetContents &Known = getKnown();11859    const SetContents &Assumed = getAssumed();11860 11861    SmallVector<StringRef, 0> Set(Known.getSet().begin(), Known.getSet().end());11862    llvm::sort(Set);11863    const std::string KnownStr = llvm::join(Set, ",");11864 11865    std::string AssumedStr = "Universal";11866    if (!Assumed.isUniversal()) {11867      Set.assign(Assumed.getSet().begin(), Assumed.getSet().end());11868      AssumedStr = llvm::join(Set, ",");11869    }11870    return "Known [" + KnownStr + "]," + " Assumed [" + AssumedStr + "]";11871  }11872};11873 11874/// Propagates assumption information from parent functions to all of their11875/// successors. An assumption can be propagated if the containing function11876/// dominates the called function.11877///11878/// We start with a "known" set of assumptions already valid for the associated11879/// function and an "assumed" set that initially contains all possible11880/// assumptions. The assumed set is inter-procedurally updated by narrowing its11881/// contents as concrete values are known. The concrete values are seeded by the11882/// first nodes that are either entries into the call graph, or contains no11883/// assumptions. Each node is updated as the intersection of the assumed state11884/// with all of its predecessors.11885struct AAAssumptionInfoFunction final : AAAssumptionInfoImpl {11886  AAAssumptionInfoFunction(const IRPosition &IRP, Attributor &A)11887      : AAAssumptionInfoImpl(IRP, A,11888                             getAssumptions(*IRP.getAssociatedFunction())) {}11889 11890  /// See AbstractAttribute::updateImpl(...).11891  ChangeStatus updateImpl(Attributor &A) override {11892    bool Changed = false;11893 11894    auto CallSitePred = [&](AbstractCallSite ACS) {11895      const auto *AssumptionAA = A.getAAFor<AAAssumptionInfo>(11896          *this, IRPosition::callsite_function(*ACS.getInstruction()),11897          DepClassTy::REQUIRED);11898      if (!AssumptionAA)11899        return false;11900      // Get the set of assumptions shared by all of this function's callers.11901      Changed |= getIntersection(AssumptionAA->getAssumed());11902      return !getAssumed().empty() || !getKnown().empty();11903    };11904 11905    bool UsedAssumedInformation = false;11906    // Get the intersection of all assumptions held by this node's predecessors.11907    // If we don't know all the call sites then this is either an entry into the11908    // call graph or an empty node. This node is known to only contain its own11909    // assumptions and can be propagated to its successors.11910    if (!A.checkForAllCallSites(CallSitePred, *this, true,11911                                UsedAssumedInformation))11912      return indicatePessimisticFixpoint();11913 11914    return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;11915  }11916 11917  void trackStatistics() const override {}11918};11919 11920/// Assumption Info defined for call sites.11921struct AAAssumptionInfoCallSite final : AAAssumptionInfoImpl {11922 11923  AAAssumptionInfoCallSite(const IRPosition &IRP, Attributor &A)11924      : AAAssumptionInfoImpl(IRP, A, getInitialAssumptions(IRP)) {}11925 11926  /// See AbstractAttribute::initialize(...).11927  void initialize(Attributor &A) override {11928    const IRPosition &FnPos = IRPosition::function(*getAnchorScope());11929    A.getAAFor<AAAssumptionInfo>(*this, FnPos, DepClassTy::REQUIRED);11930  }11931 11932  /// See AbstractAttribute::updateImpl(...).11933  ChangeStatus updateImpl(Attributor &A) override {11934    const IRPosition &FnPos = IRPosition::function(*getAnchorScope());11935    auto *AssumptionAA =11936        A.getAAFor<AAAssumptionInfo>(*this, FnPos, DepClassTy::REQUIRED);11937    if (!AssumptionAA)11938      return indicatePessimisticFixpoint();11939    bool Changed = getIntersection(AssumptionAA->getAssumed());11940    return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;11941  }11942 11943  /// See AbstractAttribute::trackStatistics()11944  void trackStatistics() const override {}11945 11946private:11947  /// Helper to initialized the known set as all the assumptions this call and11948  /// the callee contain.11949  DenseSet<StringRef> getInitialAssumptions(const IRPosition &IRP) {11950    const CallBase &CB = cast<CallBase>(IRP.getAssociatedValue());11951    auto Assumptions = getAssumptions(CB);11952    if (const Function *F = CB.getCaller())11953      set_union(Assumptions, getAssumptions(*F));11954    if (Function *F = IRP.getAssociatedFunction())11955      set_union(Assumptions, getAssumptions(*F));11956    return Assumptions;11957  }11958};11959} // namespace11960 11961AACallGraphNode *AACallEdgeIterator::operator*() const {11962  return static_cast<AACallGraphNode *>(const_cast<AACallEdges *>(11963      A.getOrCreateAAFor<AACallEdges>(IRPosition::function(**I))));11964}11965 11966void AttributorCallGraph::print() { llvm::WriteGraph(outs(), this); }11967 11968/// ------------------------ UnderlyingObjects ---------------------------------11969 11970namespace {11971struct AAUnderlyingObjectsImpl11972    : StateWrapper<BooleanState, AAUnderlyingObjects> {11973  using BaseTy = StateWrapper<BooleanState, AAUnderlyingObjects>;11974  AAUnderlyingObjectsImpl(const IRPosition &IRP, Attributor &A) : BaseTy(IRP) {}11975 11976  /// See AbstractAttribute::getAsStr().11977  const std::string getAsStr(Attributor *A) const override {11978    if (!isValidState())11979      return "<invalid>";11980    std::string Str;11981    llvm::raw_string_ostream OS(Str);11982    OS << "underlying objects: inter " << InterAssumedUnderlyingObjects.size()11983       << " objects, intra " << IntraAssumedUnderlyingObjects.size()11984       << " objects.\n";11985    if (!InterAssumedUnderlyingObjects.empty()) {11986      OS << "inter objects:\n";11987      for (auto *Obj : InterAssumedUnderlyingObjects)11988        OS << *Obj << '\n';11989    }11990    if (!IntraAssumedUnderlyingObjects.empty()) {11991      OS << "intra objects:\n";11992      for (auto *Obj : IntraAssumedUnderlyingObjects)11993        OS << *Obj << '\n';11994    }11995    return Str;11996  }11997 11998  /// See AbstractAttribute::trackStatistics()11999  void trackStatistics() const override {}12000 12001  /// See AbstractAttribute::updateImpl(...).12002  ChangeStatus updateImpl(Attributor &A) override {12003    auto &Ptr = getAssociatedValue();12004 12005    bool UsedAssumedInformation = false;12006    auto DoUpdate = [&](SmallSetVector<Value *, 8> &UnderlyingObjects,12007                        AA::ValueScope Scope) {12008      SmallPtrSet<Value *, 8> SeenObjects;12009      SmallVector<AA::ValueAndContext> Values;12010 12011      if (!A.getAssumedSimplifiedValues(IRPosition::value(Ptr), *this, Values,12012                                        Scope, UsedAssumedInformation))12013        return UnderlyingObjects.insert(&Ptr);12014 12015      bool Changed = false;12016 12017      for (unsigned I = 0; I < Values.size(); ++I) {12018        auto &VAC = Values[I];12019        auto *Obj = VAC.getValue();12020        Value *UO = getUnderlyingObject(Obj);12021        if (!SeenObjects.insert(UO ? UO : Obj).second)12022          continue;12023        if (UO && UO != Obj) {12024          if (isa<AllocaInst>(UO) || isa<GlobalValue>(UO)) {12025            Changed |= UnderlyingObjects.insert(UO);12026            continue;12027          }12028 12029          const auto *OtherAA = A.getAAFor<AAUnderlyingObjects>(12030              *this, IRPosition::value(*UO), DepClassTy::OPTIONAL);12031          auto Pred = [&](Value &V) {12032            if (&V == UO)12033              Changed |= UnderlyingObjects.insert(UO);12034            else12035              Values.emplace_back(V, nullptr);12036            return true;12037          };12038 12039          if (!OtherAA || !OtherAA->forallUnderlyingObjects(Pred, Scope))12040            llvm_unreachable(12041                "The forall call should not return false at this position");12042          UsedAssumedInformation |= !OtherAA->getState().isAtFixpoint();12043          continue;12044        }12045 12046        if (isa<SelectInst>(Obj)) {12047          Changed |= handleIndirect(A, *Obj, UnderlyingObjects, Scope,12048                                    UsedAssumedInformation);12049          continue;12050        }12051        if (auto *PHI = dyn_cast<PHINode>(Obj)) {12052          // Explicitly look through PHIs as we do not care about dynamically12053          // uniqueness.12054          for (unsigned u = 0, e = PHI->getNumIncomingValues(); u < e; u++) {12055            Changed |=12056                handleIndirect(A, *PHI->getIncomingValue(u), UnderlyingObjects,12057                               Scope, UsedAssumedInformation);12058          }12059          continue;12060        }12061 12062        Changed |= UnderlyingObjects.insert(Obj);12063      }12064 12065      return Changed;12066    };12067 12068    bool Changed = false;12069    Changed |= DoUpdate(IntraAssumedUnderlyingObjects, AA::Intraprocedural);12070    Changed |= DoUpdate(InterAssumedUnderlyingObjects, AA::Interprocedural);12071    if (!UsedAssumedInformation)12072      indicateOptimisticFixpoint();12073    return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;12074  }12075 12076  bool forallUnderlyingObjects(12077      function_ref<bool(Value &)> Pred,12078      AA::ValueScope Scope = AA::Interprocedural) const override {12079    if (!isValidState())12080      return Pred(getAssociatedValue());12081 12082    auto &AssumedUnderlyingObjects = Scope == AA::Intraprocedural12083                                         ? IntraAssumedUnderlyingObjects12084                                         : InterAssumedUnderlyingObjects;12085    for (Value *Obj : AssumedUnderlyingObjects)12086      if (!Pred(*Obj))12087        return false;12088 12089    return true;12090  }12091 12092private:12093  /// Handle the case where the value is not the actual underlying value, such12094  /// as a phi node or a select instruction.12095  bool handleIndirect(Attributor &A, Value &V,12096                      SmallSetVector<Value *, 8> &UnderlyingObjects,12097                      AA::ValueScope Scope, bool &UsedAssumedInformation) {12098    bool Changed = false;12099    const auto *AA = A.getAAFor<AAUnderlyingObjects>(12100        *this, IRPosition::value(V), DepClassTy::OPTIONAL);12101    auto Pred = [&](Value &V) {12102      Changed |= UnderlyingObjects.insert(&V);12103      return true;12104    };12105    if (!AA || !AA->forallUnderlyingObjects(Pred, Scope))12106      llvm_unreachable(12107          "The forall call should not return false at this position");12108    UsedAssumedInformation |= !AA->getState().isAtFixpoint();12109    return Changed;12110  }12111 12112  /// All the underlying objects collected so far via intra procedural scope.12113  SmallSetVector<Value *, 8> IntraAssumedUnderlyingObjects;12114  /// All the underlying objects collected so far via inter procedural scope.12115  SmallSetVector<Value *, 8> InterAssumedUnderlyingObjects;12116};12117 12118struct AAUnderlyingObjectsFloating final : AAUnderlyingObjectsImpl {12119  AAUnderlyingObjectsFloating(const IRPosition &IRP, Attributor &A)12120      : AAUnderlyingObjectsImpl(IRP, A) {}12121};12122 12123struct AAUnderlyingObjectsArgument final : AAUnderlyingObjectsImpl {12124  AAUnderlyingObjectsArgument(const IRPosition &IRP, Attributor &A)12125      : AAUnderlyingObjectsImpl(IRP, A) {}12126};12127 12128struct AAUnderlyingObjectsCallSite final : AAUnderlyingObjectsImpl {12129  AAUnderlyingObjectsCallSite(const IRPosition &IRP, Attributor &A)12130      : AAUnderlyingObjectsImpl(IRP, A) {}12131};12132 12133struct AAUnderlyingObjectsCallSiteArgument final : AAUnderlyingObjectsImpl {12134  AAUnderlyingObjectsCallSiteArgument(const IRPosition &IRP, Attributor &A)12135      : AAUnderlyingObjectsImpl(IRP, A) {}12136};12137 12138struct AAUnderlyingObjectsReturned final : AAUnderlyingObjectsImpl {12139  AAUnderlyingObjectsReturned(const IRPosition &IRP, Attributor &A)12140      : AAUnderlyingObjectsImpl(IRP, A) {}12141};12142 12143struct AAUnderlyingObjectsCallSiteReturned final : AAUnderlyingObjectsImpl {12144  AAUnderlyingObjectsCallSiteReturned(const IRPosition &IRP, Attributor &A)12145      : AAUnderlyingObjectsImpl(IRP, A) {}12146};12147 12148struct AAUnderlyingObjectsFunction final : AAUnderlyingObjectsImpl {12149  AAUnderlyingObjectsFunction(const IRPosition &IRP, Attributor &A)12150      : AAUnderlyingObjectsImpl(IRP, A) {}12151};12152} // namespace12153 12154/// ------------------------ Global Value Info  -------------------------------12155namespace {12156struct AAGlobalValueInfoFloating : public AAGlobalValueInfo {12157  AAGlobalValueInfoFloating(const IRPosition &IRP, Attributor &A)12158      : AAGlobalValueInfo(IRP, A) {}12159 12160  /// See AbstractAttribute::initialize(...).12161  void initialize(Attributor &A) override {}12162 12163  bool checkUse(Attributor &A, const Use &U, bool &Follow,12164                SmallVectorImpl<const Value *> &Worklist) {12165    Instruction *UInst = dyn_cast<Instruction>(U.getUser());12166    if (!UInst) {12167      Follow = true;12168      return true;12169    }12170 12171    LLVM_DEBUG(dbgs() << "[AAGlobalValueInfo] Check use: " << *U.get() << " in "12172                      << *UInst << "\n");12173 12174    if (auto *Cmp = dyn_cast<ICmpInst>(U.getUser())) {12175      int Idx = &Cmp->getOperandUse(0) == &U;12176      if (isa<Constant>(Cmp->getOperand(Idx)))12177        return true;12178      return U == &getAnchorValue();12179    }12180 12181    // Explicitly catch return instructions.12182    if (isa<ReturnInst>(UInst)) {12183      auto CallSitePred = [&](AbstractCallSite ACS) {12184        Worklist.push_back(ACS.getInstruction());12185        return true;12186      };12187      bool UsedAssumedInformation = false;12188      // TODO: We should traverse the uses or add a "non-call-site" CB.12189      if (!A.checkForAllCallSites(CallSitePred, *UInst->getFunction(),12190                                  /*RequireAllCallSites=*/true, this,12191                                  UsedAssumedInformation))12192        return false;12193      return true;12194    }12195 12196    // For now we only use special logic for call sites. However, the tracker12197    // itself knows about a lot of other non-capturing cases already.12198    auto *CB = dyn_cast<CallBase>(UInst);12199    if (!CB)12200      return false;12201    // Direct calls are OK uses.12202    if (CB->isCallee(&U))12203      return true;12204    // Non-argument uses are scary.12205    if (!CB->isArgOperand(&U))12206      return false;12207    // TODO: Iterate callees.12208    auto *Fn = dyn_cast<Function>(CB->getCalledOperand());12209    if (!Fn || !A.isFunctionIPOAmendable(*Fn))12210      return false;12211 12212    unsigned ArgNo = CB->getArgOperandNo(&U);12213    Worklist.push_back(Fn->getArg(ArgNo));12214    return true;12215  }12216 12217  ChangeStatus updateImpl(Attributor &A) override {12218    unsigned NumUsesBefore = Uses.size();12219 12220    SmallPtrSet<const Value *, 8> Visited;12221    SmallVector<const Value *> Worklist;12222    Worklist.push_back(&getAnchorValue());12223 12224    auto UsePred = [&](const Use &U, bool &Follow) -> bool {12225      Uses.insert(&U);12226      // TODO(captures): Make this more precise.12227      UseCaptureInfo CI = DetermineUseCaptureKind(U, /*Base=*/nullptr);12228      if (CI.isPassthrough()) {12229        Follow = true;12230        return true;12231      }12232      return checkUse(A, U, Follow, Worklist);12233    };12234    auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {12235      Uses.insert(&OldU);12236      return true;12237    };12238 12239    while (!Worklist.empty()) {12240      const Value *V = Worklist.pop_back_val();12241      if (!Visited.insert(V).second)12242        continue;12243      if (!A.checkForAllUses(UsePred, *this, *V,12244                             /* CheckBBLivenessOnly */ true,12245                             DepClassTy::OPTIONAL,12246                             /* IgnoreDroppableUses */ true, EquivalentUseCB)) {12247        return indicatePessimisticFixpoint();12248      }12249    }12250 12251    return Uses.size() == NumUsesBefore ? ChangeStatus::UNCHANGED12252                                        : ChangeStatus::CHANGED;12253  }12254 12255  bool isPotentialUse(const Use &U) const override {12256    return !isValidState() || Uses.contains(&U);12257  }12258 12259  /// See AbstractAttribute::manifest(...).12260  ChangeStatus manifest(Attributor &A) override {12261    return ChangeStatus::UNCHANGED;12262  }12263 12264  /// See AbstractAttribute::getAsStr().12265  const std::string getAsStr(Attributor *A) const override {12266    return "[" + std::to_string(Uses.size()) + " uses]";12267  }12268 12269  void trackStatistics() const override {12270    STATS_DECLTRACK_FLOATING_ATTR(GlobalValuesTracked);12271  }12272 12273private:12274  /// Set of (transitive) uses of this GlobalValue.12275  SmallPtrSet<const Use *, 8> Uses;12276};12277} // namespace12278 12279/// ------------------------ Indirect Call Info  -------------------------------12280namespace {12281struct AAIndirectCallInfoCallSite : public AAIndirectCallInfo {12282  AAIndirectCallInfoCallSite(const IRPosition &IRP, Attributor &A)12283      : AAIndirectCallInfo(IRP, A) {}12284 12285  /// See AbstractAttribute::initialize(...).12286  void initialize(Attributor &A) override {12287    auto *MD = getCtxI()->getMetadata(LLVMContext::MD_callees);12288    if (!MD && !A.isClosedWorldModule())12289      return;12290 12291    if (MD) {12292      for (const auto &Op : MD->operands())12293        if (Function *Callee = mdconst::dyn_extract_or_null<Function>(Op))12294          PotentialCallees.insert(Callee);12295    } else if (A.isClosedWorldModule()) {12296      ArrayRef<Function *> IndirectlyCallableFunctions =12297          A.getInfoCache().getIndirectlyCallableFunctions(A);12298      PotentialCallees.insert_range(IndirectlyCallableFunctions);12299    }12300 12301    if (PotentialCallees.empty())12302      indicateOptimisticFixpoint();12303  }12304 12305  ChangeStatus updateImpl(Attributor &A) override {12306    CallBase *CB = cast<CallBase>(getCtxI());12307    const Use &CalleeUse = CB->getCalledOperandUse();12308    Value *FP = CB->getCalledOperand();12309 12310    SmallSetVector<Function *, 4> AssumedCalleesNow;12311    bool AllCalleesKnownNow = AllCalleesKnown;12312 12313    auto CheckPotentialCalleeUse = [&](Function &PotentialCallee,12314                                       bool &UsedAssumedInformation) {12315      const auto *GIAA = A.getAAFor<AAGlobalValueInfo>(12316          *this, IRPosition::value(PotentialCallee), DepClassTy::OPTIONAL);12317      if (!GIAA || GIAA->isPotentialUse(CalleeUse))12318        return true;12319      UsedAssumedInformation = !GIAA->isAtFixpoint();12320      return false;12321    };12322 12323    auto AddPotentialCallees = [&]() {12324      for (auto *PotentialCallee : PotentialCallees) {12325        bool UsedAssumedInformation = false;12326        if (CheckPotentialCalleeUse(*PotentialCallee, UsedAssumedInformation))12327          AssumedCalleesNow.insert(PotentialCallee);12328      }12329    };12330 12331    // Use simplification to find potential callees, if !callees was present,12332    // fallback to that set if necessary.12333    bool UsedAssumedInformation = false;12334    SmallVector<AA::ValueAndContext> Values;12335    if (!A.getAssumedSimplifiedValues(IRPosition::value(*FP), this, Values,12336                                      AA::ValueScope::AnyScope,12337                                      UsedAssumedInformation)) {12338      if (PotentialCallees.empty())12339        return indicatePessimisticFixpoint();12340      AddPotentialCallees();12341    }12342 12343    // Try to find a reason for \p Fn not to be a potential callee. If none was12344    // found, add it to the assumed callees set.12345    auto CheckPotentialCallee = [&](Function &Fn) {12346      if (!PotentialCallees.empty() && !PotentialCallees.count(&Fn))12347        return false;12348 12349      auto &CachedResult = FilterResults[&Fn];12350      if (CachedResult.has_value())12351        return CachedResult.value();12352 12353      bool UsedAssumedInformation = false;12354      if (!CheckPotentialCalleeUse(Fn, UsedAssumedInformation)) {12355        if (!UsedAssumedInformation)12356          CachedResult = false;12357        return false;12358      }12359 12360      int NumFnArgs = Fn.arg_size();12361      int NumCBArgs = CB->arg_size();12362 12363      // Check if any excess argument (which we fill up with poison) is known to12364      // be UB on undef.12365      for (int I = NumCBArgs; I < NumFnArgs; ++I) {12366        bool IsKnown = false;12367        if (AA::hasAssumedIRAttr<Attribute::NoUndef>(12368                A, this, IRPosition::argument(*Fn.getArg(I)),12369                DepClassTy::OPTIONAL, IsKnown)) {12370          if (IsKnown)12371            CachedResult = false;12372          return false;12373        }12374      }12375 12376      CachedResult = true;12377      return true;12378    };12379 12380    // Check simplification result, prune known UB callees, also restrict it to12381    // the !callees set, if present.12382    for (auto &VAC : Values) {12383      if (isa<UndefValue>(VAC.getValue()))12384        continue;12385      if (isa<ConstantPointerNull>(VAC.getValue()) &&12386          VAC.getValue()->getType()->getPointerAddressSpace() == 0)12387        continue;12388      // TODO: Check for known UB, e.g., poison + noundef.12389      if (auto *VACFn = dyn_cast<Function>(VAC.getValue())) {12390        if (CheckPotentialCallee(*VACFn))12391          AssumedCalleesNow.insert(VACFn);12392        continue;12393      }12394      if (!PotentialCallees.empty()) {12395        AddPotentialCallees();12396        break;12397      }12398      AllCalleesKnownNow = false;12399    }12400 12401    if (AssumedCalleesNow == AssumedCallees &&12402        AllCalleesKnown == AllCalleesKnownNow)12403      return ChangeStatus::UNCHANGED;12404 12405    std::swap(AssumedCallees, AssumedCalleesNow);12406    AllCalleesKnown = AllCalleesKnownNow;12407    return ChangeStatus::CHANGED;12408  }12409 12410  /// See AbstractAttribute::manifest(...).12411  ChangeStatus manifest(Attributor &A) override {12412    // If we can't specialize at all, give up now.12413    if (!AllCalleesKnown && AssumedCallees.empty())12414      return ChangeStatus::UNCHANGED;12415 12416    CallBase *CB = cast<CallBase>(getCtxI());12417    bool UsedAssumedInformation = false;12418    if (A.isAssumedDead(*CB, this, /*LivenessAA=*/nullptr,12419                        UsedAssumedInformation))12420      return ChangeStatus::UNCHANGED;12421 12422    ChangeStatus Changed = ChangeStatus::UNCHANGED;12423    Value *FP = CB->getCalledOperand();12424    if (FP->getType()->getPointerAddressSpace())12425      FP = new AddrSpaceCastInst(FP, PointerType::get(FP->getContext(), 0),12426                                 FP->getName() + ".as0", CB->getIterator());12427 12428    bool CBIsVoid = CB->getType()->isVoidTy();12429    BasicBlock::iterator IP = CB->getIterator();12430    FunctionType *CSFT = CB->getFunctionType();12431    SmallVector<Value *> CSArgs(CB->args());12432 12433    // If we know all callees and there are none, the call site is (effectively)12434    // dead (or UB).12435    if (AssumedCallees.empty()) {12436      assert(AllCalleesKnown &&12437             "Expected all callees to be known if there are none.");12438      A.changeToUnreachableAfterManifest(CB);12439      return ChangeStatus::CHANGED;12440    }12441 12442    // Special handling for the single callee case.12443    if (AllCalleesKnown && AssumedCallees.size() == 1) {12444      auto *NewCallee = AssumedCallees.front();12445      if (isLegalToPromote(*CB, NewCallee)) {12446        promoteCall(*CB, NewCallee, nullptr);12447        NumIndirectCallsPromoted++;12448        return ChangeStatus::CHANGED;12449      }12450      Instruction *NewCall =12451          CallInst::Create(FunctionCallee(CSFT, NewCallee), CSArgs,12452                           CB->getName(), CB->getIterator());12453      if (!CBIsVoid)12454        A.changeAfterManifest(IRPosition::callsite_returned(*CB), *NewCall);12455      A.deleteAfterManifest(*CB);12456      return ChangeStatus::CHANGED;12457    }12458 12459    // For each potential value we create a conditional12460    //12461    // ```12462    // if (ptr == value) value(args);12463    // else ...12464    // ```12465    //12466    bool SpecializedForAnyCallees = false;12467    bool SpecializedForAllCallees = AllCalleesKnown;12468    ICmpInst *LastCmp = nullptr;12469    SmallVector<Function *, 8> SkippedAssumedCallees;12470    SmallVector<std::pair<CallInst *, Instruction *>> NewCalls;12471    for (Function *NewCallee : AssumedCallees) {12472      if (!A.shouldSpecializeCallSiteForCallee(*this, *CB, *NewCallee,12473                                               AssumedCallees.size())) {12474        SkippedAssumedCallees.push_back(NewCallee);12475        SpecializedForAllCallees = false;12476        continue;12477      }12478      SpecializedForAnyCallees = true;12479 12480      LastCmp = new ICmpInst(IP, llvm::CmpInst::ICMP_EQ, FP, NewCallee);12481      Instruction *ThenTI =12482          SplitBlockAndInsertIfThen(LastCmp, IP, /* Unreachable */ false);12483      BasicBlock *CBBB = CB->getParent();12484      A.registerManifestAddedBasicBlock(*ThenTI->getParent());12485      A.registerManifestAddedBasicBlock(*IP->getParent());12486      auto *SplitTI = cast<BranchInst>(LastCmp->getNextNode());12487      BasicBlock *ElseBB;12488      if (&*IP == CB) {12489        ElseBB = BasicBlock::Create(ThenTI->getContext(), "",12490                                    ThenTI->getFunction(), CBBB);12491        A.registerManifestAddedBasicBlock(*ElseBB);12492        IP = BranchInst::Create(CBBB, ElseBB)->getIterator();12493        SplitTI->replaceUsesOfWith(CBBB, ElseBB);12494      } else {12495        ElseBB = IP->getParent();12496        ThenTI->replaceUsesOfWith(ElseBB, CBBB);12497      }12498      CastInst *RetBC = nullptr;12499      CallInst *NewCall = nullptr;12500      if (isLegalToPromote(*CB, NewCallee)) {12501        auto *CBClone = cast<CallBase>(CB->clone());12502        CBClone->insertBefore(ThenTI->getIterator());12503        NewCall = &cast<CallInst>(promoteCall(*CBClone, NewCallee, &RetBC));12504        NumIndirectCallsPromoted++;12505      } else {12506        NewCall = CallInst::Create(FunctionCallee(CSFT, NewCallee), CSArgs,12507                                   CB->getName(), ThenTI->getIterator());12508      }12509      NewCalls.push_back({NewCall, RetBC});12510    }12511 12512    auto AttachCalleeMetadata = [&](CallBase &IndirectCB) {12513      if (!AllCalleesKnown)12514        return ChangeStatus::UNCHANGED;12515      MDBuilder MDB(IndirectCB.getContext());12516      MDNode *Callees = MDB.createCallees(SkippedAssumedCallees);12517      IndirectCB.setMetadata(LLVMContext::MD_callees, Callees);12518      return ChangeStatus::CHANGED;12519    };12520 12521    if (!SpecializedForAnyCallees)12522      return AttachCalleeMetadata(*CB);12523 12524    // Check if we need the fallback indirect call still.12525    if (SpecializedForAllCallees) {12526      LastCmp->replaceAllUsesWith(ConstantInt::getTrue(LastCmp->getContext()));12527      LastCmp->eraseFromParent();12528      new UnreachableInst(IP->getContext(), IP);12529      IP->eraseFromParent();12530    } else {12531      auto *CBClone = cast<CallInst>(CB->clone());12532      CBClone->setName(CB->getName());12533      CBClone->insertBefore(*IP->getParent(), IP);12534      NewCalls.push_back({CBClone, nullptr});12535      AttachCalleeMetadata(*CBClone);12536    }12537 12538    // Check if we need a PHI to merge the results.12539    if (!CBIsVoid) {12540      auto *PHI = PHINode::Create(CB->getType(), NewCalls.size(),12541                                  CB->getName() + ".phi",12542                                  CB->getParent()->getFirstInsertionPt());12543      for (auto &It : NewCalls) {12544        CallBase *NewCall = It.first;12545        Instruction *CallRet = It.second ? It.second : It.first;12546        if (CallRet->getType() == CB->getType())12547          PHI->addIncoming(CallRet, CallRet->getParent());12548        else if (NewCall->getType()->isVoidTy())12549          PHI->addIncoming(PoisonValue::get(CB->getType()),12550                           NewCall->getParent());12551        else12552          llvm_unreachable("Call return should match or be void!");12553      }12554      A.changeAfterManifest(IRPosition::callsite_returned(*CB), *PHI);12555    }12556 12557    A.deleteAfterManifest(*CB);12558    Changed = ChangeStatus::CHANGED;12559 12560    return Changed;12561  }12562 12563  /// See AbstractAttribute::getAsStr().12564  const std::string getAsStr(Attributor *A) const override {12565    return std::string(AllCalleesKnown ? "eliminate" : "specialize") +12566           " indirect call site with " + std::to_string(AssumedCallees.size()) +12567           " functions";12568  }12569 12570  void trackStatistics() const override {12571    if (AllCalleesKnown) {12572      STATS_DECLTRACK(12573          Eliminated, CallSites,12574          "Number of indirect call sites eliminated via specialization")12575    } else {12576      STATS_DECLTRACK(Specialized, CallSites,12577                      "Number of indirect call sites specialized")12578    }12579  }12580 12581  bool foreachCallee(function_ref<bool(Function *)> CB) const override {12582    return isValidState() && AllCalleesKnown && all_of(AssumedCallees, CB);12583  }12584 12585private:12586  /// Map to remember filter results.12587  DenseMap<Function *, std::optional<bool>> FilterResults;12588 12589  /// If the !callee metadata was present, this set will contain all potential12590  /// callees (superset).12591  SmallSetVector<Function *, 4> PotentialCallees;12592 12593  /// This set contains all currently assumed calllees, which might grow over12594  /// time.12595  SmallSetVector<Function *, 4> AssumedCallees;12596 12597  /// Flag to indicate if all possible callees are in the AssumedCallees set or12598  /// if there could be others.12599  bool AllCalleesKnown = true;12600};12601} // namespace12602 12603/// --------------------- Invariant Load Pointer -------------------------------12604namespace {12605 12606struct AAInvariantLoadPointerImpl12607    : public StateWrapper<BitIntegerState<uint8_t, 15>,12608                          AAInvariantLoadPointer> {12609 12610  enum {12611    // pointer does not alias within the bounds of the function12612    IS_NOALIAS = 1 << 0,12613    // pointer is not involved in any effectful instructions within the bounds12614    // of the function12615    IS_NOEFFECT = 1 << 1,12616    // loads are invariant within the bounds of the function12617    IS_LOCALLY_INVARIANT = 1 << 2,12618    // memory lifetime is constrained within the bounds of the function12619    IS_LOCALLY_CONSTRAINED = 1 << 3,12620 12621    IS_BEST_STATE = IS_NOALIAS | IS_NOEFFECT | IS_LOCALLY_INVARIANT |12622                    IS_LOCALLY_CONSTRAINED,12623  };12624  static_assert(getBestState() == IS_BEST_STATE, "Unexpected best state");12625 12626  using Base =12627      StateWrapper<BitIntegerState<uint8_t, 15>, AAInvariantLoadPointer>;12628 12629  // the BitIntegerState is optimistic about IS_NOALIAS and IS_NOEFFECT, but12630  // pessimistic about IS_KNOWN_INVARIANT12631  AAInvariantLoadPointerImpl(const IRPosition &IRP, Attributor &A)12632      : Base(IRP) {}12633 12634  bool isKnownInvariant() const final {12635    return isKnownLocallyInvariant() && isKnown(IS_LOCALLY_CONSTRAINED);12636  }12637 12638  bool isKnownLocallyInvariant() const final {12639    if (isKnown(IS_LOCALLY_INVARIANT))12640      return true;12641    return isKnown(IS_NOALIAS | IS_NOEFFECT);12642  }12643 12644  bool isAssumedInvariant() const final {12645    return isAssumedLocallyInvariant() && isAssumed(IS_LOCALLY_CONSTRAINED);12646  }12647 12648  bool isAssumedLocallyInvariant() const final {12649    if (isAssumed(IS_LOCALLY_INVARIANT))12650      return true;12651    return isAssumed(IS_NOALIAS | IS_NOEFFECT);12652  }12653 12654  ChangeStatus updateImpl(Attributor &A) override {12655    ChangeStatus Changed = ChangeStatus::UNCHANGED;12656 12657    Changed |= updateNoAlias(A);12658    if (requiresNoAlias() && !isAssumed(IS_NOALIAS))12659      return indicatePessimisticFixpoint();12660 12661    Changed |= updateNoEffect(A);12662 12663    Changed |= updateLocalInvariance(A);12664 12665    return Changed;12666  }12667 12668  ChangeStatus manifest(Attributor &A) override {12669    if (!isKnownInvariant())12670      return ChangeStatus::UNCHANGED;12671 12672    ChangeStatus Changed = ChangeStatus::UNCHANGED;12673    const Value *Ptr = &getAssociatedValue();12674    const auto TagInvariantLoads = [&](const Use &U, bool &) {12675      if (U.get() != Ptr)12676        return true;12677      auto *I = dyn_cast<Instruction>(U.getUser());12678      if (!I)12679        return true;12680 12681      // Ensure that we are only changing uses from the corresponding callgraph12682      // SSC in the case that the AA isn't run on the entire module12683      if (!A.isRunOn(I->getFunction()))12684        return true;12685 12686      if (I->hasMetadata(LLVMContext::MD_invariant_load))12687        return true;12688 12689      if (auto *LI = dyn_cast<LoadInst>(I)) {12690        LI->setMetadata(LLVMContext::MD_invariant_load,12691                        MDNode::get(LI->getContext(), {}));12692        Changed = ChangeStatus::CHANGED;12693      }12694      return true;12695    };12696 12697    (void)A.checkForAllUses(TagInvariantLoads, *this, *Ptr);12698    return Changed;12699  }12700 12701  /// See AbstractAttribute::getAsStr().12702  const std::string getAsStr(Attributor *) const override {12703    if (isKnownInvariant())12704      return "load-invariant pointer";12705    return "non-invariant pointer";12706  }12707 12708  /// See AbstractAttribute::trackStatistics().12709  void trackStatistics() const override {}12710 12711private:12712  /// Indicate that noalias is required for the pointer to be invariant.12713  bool requiresNoAlias() const {12714    switch (getPositionKind()) {12715    default:12716      // Conservatively default to require noalias.12717      return true;12718    case IRP_FLOAT:12719    case IRP_RETURNED:12720    case IRP_CALL_SITE:12721      return false;12722    case IRP_CALL_SITE_RETURNED: {12723      const auto &CB = cast<CallBase>(getAnchorValue());12724      return !isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(12725          &CB, /*MustPreserveNullness=*/false);12726    }12727    case IRP_ARGUMENT: {12728      const Function *F = getAssociatedFunction();12729      assert(F && "no associated function for argument");12730      return !isCallableCC(F->getCallingConv());12731    }12732    }12733  }12734 12735  bool isExternal() const {12736    const Function *F = getAssociatedFunction();12737    if (!F)12738      return true;12739    return isCallableCC(F->getCallingConv()) &&12740           getPositionKind() != IRP_CALL_SITE_RETURNED;12741  }12742 12743  ChangeStatus updateNoAlias(Attributor &A) {12744    if (isKnown(IS_NOALIAS) || !isAssumed(IS_NOALIAS))12745      return ChangeStatus::UNCHANGED;12746 12747    // Try to use AANoAlias.12748    if (const auto *ANoAlias = A.getOrCreateAAFor<AANoAlias>(12749            getIRPosition(), this, DepClassTy::REQUIRED)) {12750      if (ANoAlias->isKnownNoAlias()) {12751        addKnownBits(IS_NOALIAS);12752        return ChangeStatus::CHANGED;12753      }12754 12755      if (!ANoAlias->isAssumedNoAlias()) {12756        removeAssumedBits(IS_NOALIAS);12757        return ChangeStatus::CHANGED;12758      }12759 12760      return ChangeStatus::UNCHANGED;12761    }12762 12763    // Try to infer noalias from argument attribute, since it is applicable for12764    // the duration of the function.12765    if (const Argument *Arg = getAssociatedArgument()) {12766      if (Arg->hasNoAliasAttr()) {12767        addKnownBits(IS_NOALIAS);12768        return ChangeStatus::UNCHANGED;12769      }12770 12771      // Noalias information is not provided, and cannot be inferred,12772      // so we conservatively assume the pointer aliases.12773      removeAssumedBits(IS_NOALIAS);12774      return ChangeStatus::CHANGED;12775    }12776 12777    return ChangeStatus::UNCHANGED;12778  }12779 12780  ChangeStatus updateNoEffect(Attributor &A) {12781    if (isKnown(IS_NOEFFECT) || !isAssumed(IS_NOEFFECT))12782      return ChangeStatus::UNCHANGED;12783 12784    if (!getAssociatedFunction())12785      return indicatePessimisticFixpoint();12786 12787    if (isa<AllocaInst>(&getAssociatedValue()))12788      return indicatePessimisticFixpoint();12789 12790    const auto HasNoEffectLoads = [&](const Use &U, bool &) {12791      const auto *LI = dyn_cast<LoadInst>(U.getUser());12792      return !LI || !LI->mayHaveSideEffects();12793    };12794    if (!A.checkForAllUses(HasNoEffectLoads, *this, getAssociatedValue()))12795      return indicatePessimisticFixpoint();12796 12797    if (const auto *AMemoryBehavior = A.getOrCreateAAFor<AAMemoryBehavior>(12798            getIRPosition(), this, DepClassTy::REQUIRED)) {12799      // For non-instructions, try to use AAMemoryBehavior to infer the readonly12800      // attribute12801      if (!AMemoryBehavior->isAssumedReadOnly())12802        return indicatePessimisticFixpoint();12803 12804      if (AMemoryBehavior->isKnownReadOnly()) {12805        addKnownBits(IS_NOEFFECT);12806        return ChangeStatus::UNCHANGED;12807      }12808 12809      return ChangeStatus::UNCHANGED;12810    }12811 12812    if (const Argument *Arg = getAssociatedArgument()) {12813      if (Arg->onlyReadsMemory()) {12814        addKnownBits(IS_NOEFFECT);12815        return ChangeStatus::UNCHANGED;12816      }12817 12818      // Readonly information is not provided, and cannot be inferred from12819      // AAMemoryBehavior.12820      return indicatePessimisticFixpoint();12821    }12822 12823    return ChangeStatus::UNCHANGED;12824  }12825 12826  ChangeStatus updateLocalInvariance(Attributor &A) {12827    if (isKnown(IS_LOCALLY_INVARIANT) || !isAssumed(IS_LOCALLY_INVARIANT))12828      return ChangeStatus::UNCHANGED;12829 12830    // try to infer invariance from underlying objects12831    const auto *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(12832        getIRPosition(), this, DepClassTy::REQUIRED);12833    if (!AUO)12834      return ChangeStatus::UNCHANGED;12835 12836    bool UsedAssumedInformation = false;12837    const auto IsLocallyInvariantLoadIfPointer = [&](const Value &V) {12838      if (!V.getType()->isPointerTy())12839        return true;12840      const auto *IsInvariantLoadPointer =12841          A.getOrCreateAAFor<AAInvariantLoadPointer>(IRPosition::value(V), this,12842                                                     DepClassTy::REQUIRED);12843      // Conservatively fail if invariance cannot be inferred.12844      if (!IsInvariantLoadPointer)12845        return false;12846 12847      if (IsInvariantLoadPointer->isKnownLocallyInvariant())12848        return true;12849      if (!IsInvariantLoadPointer->isAssumedLocallyInvariant())12850        return false;12851 12852      UsedAssumedInformation = true;12853      return true;12854    };12855    if (!AUO->forallUnderlyingObjects(IsLocallyInvariantLoadIfPointer))12856      return indicatePessimisticFixpoint();12857 12858    if (const auto *CB = dyn_cast<CallBase>(&getAnchorValue())) {12859      if (isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(12860              CB, /*MustPreserveNullness=*/false)) {12861        for (const Value *Arg : CB->args()) {12862          if (!IsLocallyInvariantLoadIfPointer(*Arg))12863            return indicatePessimisticFixpoint();12864        }12865      }12866    }12867 12868    if (!UsedAssumedInformation) {12869      // Pointer is known and not just assumed to be locally invariant.12870      addKnownBits(IS_LOCALLY_INVARIANT);12871      return ChangeStatus::CHANGED;12872    }12873 12874    return ChangeStatus::UNCHANGED;12875  }12876};12877 12878struct AAInvariantLoadPointerFloating final : AAInvariantLoadPointerImpl {12879  AAInvariantLoadPointerFloating(const IRPosition &IRP, Attributor &A)12880      : AAInvariantLoadPointerImpl(IRP, A) {}12881};12882 12883struct AAInvariantLoadPointerReturned final : AAInvariantLoadPointerImpl {12884  AAInvariantLoadPointerReturned(const IRPosition &IRP, Attributor &A)12885      : AAInvariantLoadPointerImpl(IRP, A) {}12886 12887  void initialize(Attributor &) override {12888    removeAssumedBits(IS_LOCALLY_CONSTRAINED);12889  }12890};12891 12892struct AAInvariantLoadPointerCallSiteReturned final12893    : AAInvariantLoadPointerImpl {12894  AAInvariantLoadPointerCallSiteReturned(const IRPosition &IRP, Attributor &A)12895      : AAInvariantLoadPointerImpl(IRP, A) {}12896 12897  void initialize(Attributor &A) override {12898    const Function *F = getAssociatedFunction();12899    assert(F && "no associated function for return from call");12900 12901    if (!F->isDeclaration() && !F->isIntrinsic())12902      return AAInvariantLoadPointerImpl::initialize(A);12903 12904    const auto &CB = cast<CallBase>(getAnchorValue());12905    if (isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(12906            &CB, /*MustPreserveNullness=*/false))12907      return AAInvariantLoadPointerImpl::initialize(A);12908 12909    if (F->onlyReadsMemory() && F->hasNoSync())12910      return AAInvariantLoadPointerImpl::initialize(A);12911 12912    // At this point, the function is opaque, so we conservatively assume12913    // non-invariance.12914    indicatePessimisticFixpoint();12915  }12916};12917 12918struct AAInvariantLoadPointerArgument final : AAInvariantLoadPointerImpl {12919  AAInvariantLoadPointerArgument(const IRPosition &IRP, Attributor &A)12920      : AAInvariantLoadPointerImpl(IRP, A) {}12921 12922  void initialize(Attributor &) override {12923    const Function *F = getAssociatedFunction();12924    assert(F && "no associated function for argument");12925 12926    if (!isCallableCC(F->getCallingConv())) {12927      addKnownBits(IS_LOCALLY_CONSTRAINED);12928      return;12929    }12930 12931    if (!F->hasLocalLinkage())12932      removeAssumedBits(IS_LOCALLY_CONSTRAINED);12933  }12934};12935 12936struct AAInvariantLoadPointerCallSiteArgument final12937    : AAInvariantLoadPointerImpl {12938  AAInvariantLoadPointerCallSiteArgument(const IRPosition &IRP, Attributor &A)12939      : AAInvariantLoadPointerImpl(IRP, A) {}12940};12941} // namespace12942 12943/// ------------------------ Address Space  ------------------------------------12944namespace {12945 12946template <typename InstType>12947static bool makeChange(Attributor &A, InstType *MemInst, const Use &U,12948                       Value *OriginalValue, PointerType *NewPtrTy,12949                       bool UseOriginalValue) {12950  if (U.getOperandNo() != InstType::getPointerOperandIndex())12951    return false;12952 12953  if (MemInst->isVolatile()) {12954    auto *TTI = A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(12955        *MemInst->getFunction());12956    unsigned NewAS = NewPtrTy->getPointerAddressSpace();12957    if (!TTI || !TTI->hasVolatileVariant(MemInst, NewAS))12958      return false;12959  }12960 12961  if (UseOriginalValue) {12962    A.changeUseAfterManifest(const_cast<Use &>(U), *OriginalValue);12963    return true;12964  }12965 12966  Instruction *CastInst = new AddrSpaceCastInst(OriginalValue, NewPtrTy);12967  CastInst->insertBefore(MemInst->getIterator());12968  A.changeUseAfterManifest(const_cast<Use &>(U), *CastInst);12969  return true;12970}12971 12972struct AAAddressSpaceImpl : public AAAddressSpace {12973  AAAddressSpaceImpl(const IRPosition &IRP, Attributor &A)12974      : AAAddressSpace(IRP, A) {}12975 12976  uint32_t getAddressSpace() const override {12977    assert(isValidState() && "the AA is invalid");12978    return AssumedAddressSpace;12979  }12980 12981  /// See AbstractAttribute::initialize(...).12982  void initialize(Attributor &A) override {12983    assert(getAssociatedType()->isPtrOrPtrVectorTy() &&12984           "Associated value is not a pointer");12985 12986    if (!A.getInfoCache().getFlatAddressSpace().has_value()) {12987      indicatePessimisticFixpoint();12988      return;12989    }12990 12991    unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();12992    unsigned AS = getAssociatedType()->getPointerAddressSpace();12993    if (AS != FlatAS) {12994      [[maybe_unused]] bool R = takeAddressSpace(AS);12995      assert(R && "The take should happen");12996      indicateOptimisticFixpoint();12997    }12998  }12999 13000  ChangeStatus updateImpl(Attributor &A) override {13001    uint32_t OldAddressSpace = AssumedAddressSpace;13002    unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();13003 13004    auto CheckAddressSpace = [&](Value &Obj) {13005      // Ignore undef.13006      if (isa<UndefValue>(&Obj))13007        return true;13008 13009      // If the object already has a non-flat address space, we simply take it.13010      unsigned ObjAS = Obj.getType()->getPointerAddressSpace();13011      if (ObjAS != FlatAS)13012        return takeAddressSpace(ObjAS);13013 13014      // At this point, we know Obj is in the flat address space. For a final13015      // attempt, we want to use getAssumedAddrSpace, but first we must get the13016      // associated function, if possible.13017      Function *F = nullptr;13018      if (auto *Arg = dyn_cast<Argument>(&Obj))13019        F = Arg->getParent();13020      else if (auto *I = dyn_cast<Instruction>(&Obj))13021        F = I->getFunction();13022 13023      // Use getAssumedAddrSpace if the associated function exists.13024      if (F) {13025        auto *TTI =13026            A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(*F);13027        unsigned AssumedAS = TTI->getAssumedAddrSpace(&Obj);13028        if (AssumedAS != ~0U)13029          return takeAddressSpace(AssumedAS);13030      }13031 13032      // Now we can't do anything else but to take the flat AS.13033      return takeAddressSpace(FlatAS);13034    };13035 13036    auto *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(getIRPosition(), this,13037                                                        DepClassTy::REQUIRED);13038    if (!AUO->forallUnderlyingObjects(CheckAddressSpace))13039      return indicatePessimisticFixpoint();13040 13041    return OldAddressSpace == AssumedAddressSpace ? ChangeStatus::UNCHANGED13042                                                  : ChangeStatus::CHANGED;13043  }13044 13045  /// See AbstractAttribute::manifest(...).13046  ChangeStatus manifest(Attributor &A) override {13047    unsigned NewAS = getAddressSpace();13048 13049    if (NewAS == InvalidAddressSpace ||13050        NewAS == getAssociatedType()->getPointerAddressSpace())13051      return ChangeStatus::UNCHANGED;13052 13053    unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();13054 13055    Value *AssociatedValue = &getAssociatedValue();13056    Value *OriginalValue = peelAddrspacecast(AssociatedValue, FlatAS);13057 13058    PointerType *NewPtrTy =13059        PointerType::get(getAssociatedType()->getContext(), NewAS);13060    bool UseOriginalValue =13061        OriginalValue->getType()->getPointerAddressSpace() == NewAS;13062 13063    bool Changed = false;13064 13065    auto Pred = [&](const Use &U, bool &) {13066      if (U.get() != AssociatedValue)13067        return true;13068      auto *Inst = dyn_cast<Instruction>(U.getUser());13069      if (!Inst)13070        return true;13071      // This is a WA to make sure we only change uses from the corresponding13072      // CGSCC if the AA is run on CGSCC instead of the entire module.13073      if (!A.isRunOn(Inst->getFunction()))13074        return true;13075      if (auto *LI = dyn_cast<LoadInst>(Inst)) {13076        Changed |=13077            makeChange(A, LI, U, OriginalValue, NewPtrTy, UseOriginalValue);13078      } else if (auto *SI = dyn_cast<StoreInst>(Inst)) {13079        Changed |=13080            makeChange(A, SI, U, OriginalValue, NewPtrTy, UseOriginalValue);13081      } else if (auto *RMW = dyn_cast<AtomicRMWInst>(Inst)) {13082        Changed |=13083            makeChange(A, RMW, U, OriginalValue, NewPtrTy, UseOriginalValue);13084      } else if (auto *CmpX = dyn_cast<AtomicCmpXchgInst>(Inst)) {13085        Changed |=13086            makeChange(A, CmpX, U, OriginalValue, NewPtrTy, UseOriginalValue);13087      }13088      return true;13089    };13090 13091    // It doesn't matter if we can't check all uses as we can simply13092    // conservatively ignore those that can not be visited.13093    (void)A.checkForAllUses(Pred, *this, getAssociatedValue(),13094                            /* CheckBBLivenessOnly */ true);13095 13096    return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;13097  }13098 13099  /// See AbstractAttribute::getAsStr().13100  const std::string getAsStr(Attributor *A) const override {13101    if (!isValidState())13102      return "addrspace(<invalid>)";13103    return "addrspace(" +13104           (AssumedAddressSpace == InvalidAddressSpace13105                ? "none"13106                : std::to_string(AssumedAddressSpace)) +13107           ")";13108  }13109 13110private:13111  uint32_t AssumedAddressSpace = InvalidAddressSpace;13112 13113  bool takeAddressSpace(uint32_t AS) {13114    if (AssumedAddressSpace == InvalidAddressSpace) {13115      AssumedAddressSpace = AS;13116      return true;13117    }13118    return AssumedAddressSpace == AS;13119  }13120 13121  static Value *peelAddrspacecast(Value *V, unsigned FlatAS) {13122    if (auto *I = dyn_cast<AddrSpaceCastInst>(V)) {13123      assert(I->getSrcAddressSpace() != FlatAS &&13124             "there should not be flat AS -> non-flat AS");13125      return I->getPointerOperand();13126    }13127    if (auto *C = dyn_cast<ConstantExpr>(V))13128      if (C->getOpcode() == Instruction::AddrSpaceCast) {13129        assert(C->getOperand(0)->getType()->getPointerAddressSpace() !=13130                   FlatAS &&13131               "there should not be flat AS -> non-flat AS X");13132        return C->getOperand(0);13133      }13134    return V;13135  }13136};13137 13138struct AAAddressSpaceFloating final : AAAddressSpaceImpl {13139  AAAddressSpaceFloating(const IRPosition &IRP, Attributor &A)13140      : AAAddressSpaceImpl(IRP, A) {}13141 13142  void trackStatistics() const override {13143    STATS_DECLTRACK_FLOATING_ATTR(addrspace);13144  }13145};13146 13147struct AAAddressSpaceReturned final : AAAddressSpaceImpl {13148  AAAddressSpaceReturned(const IRPosition &IRP, Attributor &A)13149      : AAAddressSpaceImpl(IRP, A) {}13150 13151  /// See AbstractAttribute::initialize(...).13152  void initialize(Attributor &A) override {13153    // TODO: we don't rewrite function argument for now because it will need to13154    // rewrite the function signature and all call sites.13155    (void)indicatePessimisticFixpoint();13156  }13157 13158  void trackStatistics() const override {13159    STATS_DECLTRACK_FNRET_ATTR(addrspace);13160  }13161};13162 13163struct AAAddressSpaceCallSiteReturned final : AAAddressSpaceImpl {13164  AAAddressSpaceCallSiteReturned(const IRPosition &IRP, Attributor &A)13165      : AAAddressSpaceImpl(IRP, A) {}13166 13167  void trackStatistics() const override {13168    STATS_DECLTRACK_CSRET_ATTR(addrspace);13169  }13170};13171 13172struct AAAddressSpaceArgument final : AAAddressSpaceImpl {13173  AAAddressSpaceArgument(const IRPosition &IRP, Attributor &A)13174      : AAAddressSpaceImpl(IRP, A) {}13175 13176  void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(addrspace); }13177};13178 13179struct AAAddressSpaceCallSiteArgument final : AAAddressSpaceImpl {13180  AAAddressSpaceCallSiteArgument(const IRPosition &IRP, Attributor &A)13181      : AAAddressSpaceImpl(IRP, A) {}13182 13183  /// See AbstractAttribute::initialize(...).13184  void initialize(Attributor &A) override {13185    // TODO: we don't rewrite call site argument for now because it will need to13186    // rewrite the function signature of the callee.13187    (void)indicatePessimisticFixpoint();13188  }13189 13190  void trackStatistics() const override {13191    STATS_DECLTRACK_CSARG_ATTR(addrspace);13192  }13193};13194} // namespace13195 13196/// ------------------------ No Alias Address Space  ---------------------------13197// This attribute assumes flat address space can alias all other address space13198 13199// TODO: this is similar to AAAddressSpace, most of the code should be merged.13200// But merging it created failing cased on gateway test that cannot be13201// reproduced locally. So should open a seperated PR to hande the merge of13202// AANoAliasAddrSpace and AAAddressSpace attribute13203 13204namespace {13205struct AANoAliasAddrSpaceImpl : public AANoAliasAddrSpace {13206  AANoAliasAddrSpaceImpl(const IRPosition &IRP, Attributor &A)13207      : AANoAliasAddrSpace(IRP, A) {}13208 13209  void initialize(Attributor &A) override {13210    assert(getAssociatedType()->isPtrOrPtrVectorTy() &&13211           "Associated value is not a pointer");13212 13213    resetASRanges(A);13214 13215    std::optional<unsigned> FlatAS = A.getInfoCache().getFlatAddressSpace();13216    if (!FlatAS.has_value()) {13217      indicatePessimisticFixpoint();13218      return;13219    }13220 13221    removeAS(*FlatAS);13222 13223    unsigned AS = getAssociatedType()->getPointerAddressSpace();13224    if (AS != *FlatAS) {13225      removeAS(AS);13226      indicateOptimisticFixpoint();13227    }13228  }13229 13230  ChangeStatus updateImpl(Attributor &A) override {13231    unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();13232    uint32_t OldAssumed = getAssumed();13233 13234    auto CheckAddressSpace = [&](Value &Obj) {13235      if (isa<PoisonValue>(&Obj))13236        return true;13237 13238      unsigned AS = Obj.getType()->getPointerAddressSpace();13239      if (AS == FlatAS)13240        return false;13241 13242      removeAS(Obj.getType()->getPointerAddressSpace());13243      return true;13244    };13245 13246    const AAUnderlyingObjects *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(13247        getIRPosition(), this, DepClassTy::REQUIRED);13248    if (!AUO->forallUnderlyingObjects(CheckAddressSpace))13249      return indicatePessimisticFixpoint();13250 13251    return OldAssumed == getAssumed() ? ChangeStatus::UNCHANGED13252                                      : ChangeStatus::CHANGED;13253  }13254 13255  /// See AbstractAttribute::manifest(...).13256  ChangeStatus manifest(Attributor &A) override {13257    unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();13258 13259    unsigned AS = getAssociatedType()->getPointerAddressSpace();13260    if (AS != FlatAS || Map.empty())13261      return ChangeStatus::UNCHANGED;13262 13263    LLVMContext &Ctx = getAssociatedValue().getContext();13264    MDNode *NoAliasASNode = nullptr;13265    MDBuilder MDB(Ctx);13266    // Has to use iterator to get the range info.13267    for (RangeMap::const_iterator I = Map.begin(); I != Map.end(); I++) {13268      if (!I.value())13269        continue;13270      unsigned Upper = I.stop();13271      unsigned Lower = I.start();13272      if (!NoAliasASNode) {13273        NoAliasASNode = MDB.createRange(APInt(32, Lower), APInt(32, Upper + 1));13274        continue;13275      }13276      MDNode *ASRange = MDB.createRange(APInt(32, Lower), APInt(32, Upper + 1));13277      NoAliasASNode = MDNode::getMostGenericRange(NoAliasASNode, ASRange);13278    }13279 13280    Value *AssociatedValue = &getAssociatedValue();13281    bool Changed = false;13282 13283    auto AddNoAliasAttr = [&](const Use &U, bool &) {13284      if (U.get() != AssociatedValue)13285        return true;13286      Instruction *Inst = dyn_cast<Instruction>(U.getUser());13287      if (!Inst || Inst->hasMetadata(LLVMContext::MD_noalias_addrspace))13288        return true;13289      if (!isa<LoadInst>(Inst) && !isa<StoreInst>(Inst) &&13290          !isa<AtomicCmpXchgInst>(Inst) && !isa<AtomicRMWInst>(Inst))13291        return true;13292      if (!A.isRunOn(Inst->getFunction()))13293        return true;13294      Inst->setMetadata(LLVMContext::MD_noalias_addrspace, NoAliasASNode);13295      Changed = true;13296      return true;13297    };13298    (void)A.checkForAllUses(AddNoAliasAttr, *this, *AssociatedValue,13299                            /*CheckBBLivenessOnly=*/true);13300    return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;13301  }13302 13303  /// See AbstractAttribute::getAsStr().13304  const std::string getAsStr(Attributor *A) const override {13305    if (!isValidState())13306      return "<invalid>";13307    std::string Str;13308    raw_string_ostream OS(Str);13309    OS << "CanNotBeAddrSpace(";13310    for (RangeMap::const_iterator I = Map.begin(); I != Map.end(); I++) {13311      unsigned Upper = I.stop();13312      unsigned Lower = I.start();13313      OS << ' ' << '[' << Upper << ',' << Lower + 1 << ')';13314    }13315    OS << " )";13316    return OS.str();13317  }13318 13319private:13320  void removeAS(unsigned AS) {13321    RangeMap::iterator I = Map.find(AS);13322 13323    if (I != Map.end()) {13324      unsigned Upper = I.stop();13325      unsigned Lower = I.start();13326      I.erase();13327      if (Upper == Lower)13328        return;13329      if (AS != ~((unsigned)0) && AS + 1 <= Upper)13330        Map.insert(AS + 1, Upper, /*what ever this variable name is=*/true);13331      if (AS != 0 && Lower <= AS - 1)13332        Map.insert(Lower, AS - 1, true);13333    }13334  }13335 13336  void resetASRanges(Attributor &A) {13337    Map.clear();13338    Map.insert(0, A.getInfoCache().getMaxAddrSpace(), true);13339  }13340};13341 13342struct AANoAliasAddrSpaceFloating final : AANoAliasAddrSpaceImpl {13343  AANoAliasAddrSpaceFloating(const IRPosition &IRP, Attributor &A)13344      : AANoAliasAddrSpaceImpl(IRP, A) {}13345 13346  void trackStatistics() const override {13347    STATS_DECLTRACK_FLOATING_ATTR(noaliasaddrspace);13348  }13349};13350 13351struct AANoAliasAddrSpaceReturned final : AANoAliasAddrSpaceImpl {13352  AANoAliasAddrSpaceReturned(const IRPosition &IRP, Attributor &A)13353      : AANoAliasAddrSpaceImpl(IRP, A) {}13354 13355  void trackStatistics() const override {13356    STATS_DECLTRACK_FNRET_ATTR(noaliasaddrspace);13357  }13358};13359 13360struct AANoAliasAddrSpaceCallSiteReturned final : AANoAliasAddrSpaceImpl {13361  AANoAliasAddrSpaceCallSiteReturned(const IRPosition &IRP, Attributor &A)13362      : AANoAliasAddrSpaceImpl(IRP, A) {}13363 13364  void trackStatistics() const override {13365    STATS_DECLTRACK_CSRET_ATTR(noaliasaddrspace);13366  }13367};13368 13369struct AANoAliasAddrSpaceArgument final : AANoAliasAddrSpaceImpl {13370  AANoAliasAddrSpaceArgument(const IRPosition &IRP, Attributor &A)13371      : AANoAliasAddrSpaceImpl(IRP, A) {}13372 13373  void trackStatistics() const override {13374    STATS_DECLTRACK_ARG_ATTR(noaliasaddrspace);13375  }13376};13377 13378struct AANoAliasAddrSpaceCallSiteArgument final : AANoAliasAddrSpaceImpl {13379  AANoAliasAddrSpaceCallSiteArgument(const IRPosition &IRP, Attributor &A)13380      : AANoAliasAddrSpaceImpl(IRP, A) {}13381 13382  void trackStatistics() const override {13383    STATS_DECLTRACK_CSARG_ATTR(noaliasaddrspace);13384  }13385};13386} // namespace13387/// ----------- Allocation Info ----------13388namespace {13389struct AAAllocationInfoImpl : public AAAllocationInfo {13390  AAAllocationInfoImpl(const IRPosition &IRP, Attributor &A)13391      : AAAllocationInfo(IRP, A) {}13392 13393  std::optional<TypeSize> getAllocatedSize() const override {13394    assert(isValidState() && "the AA is invalid");13395    return AssumedAllocatedSize;13396  }13397 13398  std::optional<TypeSize> findInitialAllocationSize(Instruction *I,13399                                                    const DataLayout &DL) {13400 13401    // TODO: implement case for malloc like instructions13402    switch (I->getOpcode()) {13403    case Instruction::Alloca: {13404      AllocaInst *AI = cast<AllocaInst>(I);13405      return AI->getAllocationSize(DL);13406    }13407    default:13408      return std::nullopt;13409    }13410  }13411 13412  ChangeStatus updateImpl(Attributor &A) override {13413 13414    const IRPosition &IRP = getIRPosition();13415    Instruction *I = IRP.getCtxI();13416 13417    // TODO: update check for malloc like calls13418    if (!isa<AllocaInst>(I))13419      return indicatePessimisticFixpoint();13420 13421    bool IsKnownNoCapture;13422    if (!AA::hasAssumedIRAttr<Attribute::Captures>(13423            A, this, IRP, DepClassTy::OPTIONAL, IsKnownNoCapture))13424      return indicatePessimisticFixpoint();13425 13426    const AAPointerInfo *PI =13427        A.getOrCreateAAFor<AAPointerInfo>(IRP, *this, DepClassTy::REQUIRED);13428 13429    if (!PI)13430      return indicatePessimisticFixpoint();13431 13432    if (!PI->getState().isValidState() || PI->reachesReturn())13433      return indicatePessimisticFixpoint();13434 13435    const DataLayout &DL = A.getDataLayout();13436    const auto AllocationSize = findInitialAllocationSize(I, DL);13437 13438    // If allocation size is nullopt, we give up.13439    if (!AllocationSize)13440      return indicatePessimisticFixpoint();13441 13442    // For zero sized allocations, we give up.13443    // Since we can't reduce further13444    if (*AllocationSize == 0)13445      return indicatePessimisticFixpoint();13446 13447    int64_t BinSize = PI->numOffsetBins();13448 13449    // TODO: implement for multiple bins13450    if (BinSize > 1)13451      return indicatePessimisticFixpoint();13452 13453    if (BinSize == 0) {13454      auto NewAllocationSize = std::make_optional<TypeSize>(0, false);13455      if (!changeAllocationSize(NewAllocationSize))13456        return ChangeStatus::UNCHANGED;13457      return ChangeStatus::CHANGED;13458    }13459 13460    // TODO: refactor this to be part of multiple bin case13461    const auto &It = PI->begin();13462 13463    // TODO: handle if Offset is not zero13464    if (It->first.Offset != 0)13465      return indicatePessimisticFixpoint();13466 13467    uint64_t SizeOfBin = It->first.Offset + It->first.Size;13468 13469    if (SizeOfBin >= *AllocationSize)13470      return indicatePessimisticFixpoint();13471 13472    auto NewAllocationSize = std::make_optional<TypeSize>(SizeOfBin * 8, false);13473 13474    if (!changeAllocationSize(NewAllocationSize))13475      return ChangeStatus::UNCHANGED;13476 13477    return ChangeStatus::CHANGED;13478  }13479 13480  /// See AbstractAttribute::manifest(...).13481  ChangeStatus manifest(Attributor &A) override {13482 13483    assert(isValidState() &&13484           "Manifest should only be called if the state is valid.");13485 13486    Instruction *I = getIRPosition().getCtxI();13487 13488    auto FixedAllocatedSizeInBits = getAllocatedSize()->getFixedValue();13489 13490    unsigned long NumBytesToAllocate = (FixedAllocatedSizeInBits + 7) / 8;13491 13492    switch (I->getOpcode()) {13493    // TODO: add case for malloc like calls13494    case Instruction::Alloca: {13495 13496      AllocaInst *AI = cast<AllocaInst>(I);13497 13498      Type *CharType = Type::getInt8Ty(I->getContext());13499 13500      auto *NumBytesToValue =13501          ConstantInt::get(I->getContext(), APInt(32, NumBytesToAllocate));13502 13503      BasicBlock::iterator insertPt = AI->getIterator();13504      insertPt = std::next(insertPt);13505      AllocaInst *NewAllocaInst =13506          new AllocaInst(CharType, AI->getAddressSpace(), NumBytesToValue,13507                         AI->getAlign(), AI->getName(), insertPt);13508 13509      if (A.changeAfterManifest(IRPosition::inst(*AI), *NewAllocaInst))13510        return ChangeStatus::CHANGED;13511 13512      break;13513    }13514    default:13515      break;13516    }13517 13518    return ChangeStatus::UNCHANGED;13519  }13520 13521  /// See AbstractAttribute::getAsStr().13522  const std::string getAsStr(Attributor *A) const override {13523    if (!isValidState())13524      return "allocationinfo(<invalid>)";13525    return "allocationinfo(" +13526           (AssumedAllocatedSize == HasNoAllocationSize13527                ? "none"13528                : std::to_string(AssumedAllocatedSize->getFixedValue())) +13529           ")";13530  }13531 13532private:13533  std::optional<TypeSize> AssumedAllocatedSize = HasNoAllocationSize;13534 13535  // Maintain the computed allocation size of the object.13536  // Returns (bool) weather the size of the allocation was modified or not.13537  bool changeAllocationSize(std::optional<TypeSize> Size) {13538    if (AssumedAllocatedSize == HasNoAllocationSize ||13539        AssumedAllocatedSize != Size) {13540      AssumedAllocatedSize = Size;13541      return true;13542    }13543    return false;13544  }13545};13546 13547struct AAAllocationInfoFloating : AAAllocationInfoImpl {13548  AAAllocationInfoFloating(const IRPosition &IRP, Attributor &A)13549      : AAAllocationInfoImpl(IRP, A) {}13550 13551  void trackStatistics() const override {13552    STATS_DECLTRACK_FLOATING_ATTR(allocationinfo);13553  }13554};13555 13556struct AAAllocationInfoReturned : AAAllocationInfoImpl {13557  AAAllocationInfoReturned(const IRPosition &IRP, Attributor &A)13558      : AAAllocationInfoImpl(IRP, A) {}13559 13560  /// See AbstractAttribute::initialize(...).13561  void initialize(Attributor &A) override {13562    // TODO: we don't rewrite function argument for now because it will need to13563    // rewrite the function signature and all call sites13564    (void)indicatePessimisticFixpoint();13565  }13566 13567  void trackStatistics() const override {13568    STATS_DECLTRACK_FNRET_ATTR(allocationinfo);13569  }13570};13571 13572struct AAAllocationInfoCallSiteReturned : AAAllocationInfoImpl {13573  AAAllocationInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)13574      : AAAllocationInfoImpl(IRP, A) {}13575 13576  void trackStatistics() const override {13577    STATS_DECLTRACK_CSRET_ATTR(allocationinfo);13578  }13579};13580 13581struct AAAllocationInfoArgument : AAAllocationInfoImpl {13582  AAAllocationInfoArgument(const IRPosition &IRP, Attributor &A)13583      : AAAllocationInfoImpl(IRP, A) {}13584 13585  void trackStatistics() const override {13586    STATS_DECLTRACK_ARG_ATTR(allocationinfo);13587  }13588};13589 13590struct AAAllocationInfoCallSiteArgument : AAAllocationInfoImpl {13591  AAAllocationInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)13592      : AAAllocationInfoImpl(IRP, A) {}13593 13594  /// See AbstractAttribute::initialize(...).13595  void initialize(Attributor &A) override {13596 13597    (void)indicatePessimisticFixpoint();13598  }13599 13600  void trackStatistics() const override {13601    STATS_DECLTRACK_CSARG_ATTR(allocationinfo);13602  }13603};13604} // namespace13605 13606const char AANoUnwind::ID = 0;13607const char AANoSync::ID = 0;13608const char AANoFree::ID = 0;13609const char AANonNull::ID = 0;13610const char AAMustProgress::ID = 0;13611const char AANoRecurse::ID = 0;13612const char AANonConvergent::ID = 0;13613const char AAWillReturn::ID = 0;13614const char AAUndefinedBehavior::ID = 0;13615const char AANoAlias::ID = 0;13616const char AAIntraFnReachability::ID = 0;13617const char AANoReturn::ID = 0;13618const char AAIsDead::ID = 0;13619const char AADereferenceable::ID = 0;13620const char AAAlign::ID = 0;13621const char AAInstanceInfo::ID = 0;13622const char AANoCapture::ID = 0;13623const char AAValueSimplify::ID = 0;13624const char AAHeapToStack::ID = 0;13625const char AAPrivatizablePtr::ID = 0;13626const char AAMemoryBehavior::ID = 0;13627const char AAMemoryLocation::ID = 0;13628const char AAValueConstantRange::ID = 0;13629const char AAPotentialConstantValues::ID = 0;13630const char AAPotentialValues::ID = 0;13631const char AANoUndef::ID = 0;13632const char AANoFPClass::ID = 0;13633const char AACallEdges::ID = 0;13634const char AAInterFnReachability::ID = 0;13635const char AAPointerInfo::ID = 0;13636const char AAAssumptionInfo::ID = 0;13637const char AAUnderlyingObjects::ID = 0;13638const char AAInvariantLoadPointer::ID = 0;13639const char AAAddressSpace::ID = 0;13640const char AANoAliasAddrSpace::ID = 0;13641const char AAAllocationInfo::ID = 0;13642const char AAIndirectCallInfo::ID = 0;13643const char AAGlobalValueInfo::ID = 0;13644const char AADenormalFPMath::ID = 0;13645 13646// Macro magic to create the static generator function for attributes that13647// follow the naming scheme.13648 13649#define SWITCH_PK_INV(CLASS, PK, POS_NAME)                                     \13650  case IRPosition::PK:                                                         \13651    llvm_unreachable("Cannot create " #CLASS " for a " POS_NAME " position!");13652 13653#define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX)                               \13654  case IRPosition::PK:                                                         \13655    AA = new (A.Allocator) CLASS##SUFFIX(IRP, A);                              \13656    ++NumAAs;                                                                  \13657    break;13658 13659#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)                 \13660  CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) {      \13661    CLASS *AA = nullptr;                                                       \13662    switch (IRP.getPositionKind()) {                                           \13663      SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid")                             \13664      SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating")                              \13665      SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument")                           \13666      SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned")                           \13667      SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned")       \13668      SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument")       \13669      SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function)                     \13670      SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite)                    \13671    }                                                                          \13672    return *AA;                                                                \13673  }13674 13675#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)                    \13676  CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) {      \13677    CLASS *AA = nullptr;                                                       \13678    switch (IRP.getPositionKind()) {                                           \13679      SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid")                             \13680      SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function")                           \13681      SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site")                         \13682      SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating)                        \13683      SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument)                     \13684      SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned)                     \13685      SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned)   \13686      SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument)   \13687    }                                                                          \13688    return *AA;                                                                \13689  }13690 13691#define CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(POS, SUFFIX, CLASS)         \13692  CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) {      \13693    CLASS *AA = nullptr;                                                       \13694    switch (IRP.getPositionKind()) {                                           \13695      SWITCH_PK_CREATE(CLASS, IRP, POS, SUFFIX)                                \13696    default:                                                                   \13697      llvm_unreachable("Cannot create " #CLASS " for position otherthan " #POS \13698                       " position!");                                          \13699    }                                                                          \13700    return *AA;                                                                \13701  }13702 13703#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)                      \13704  CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) {      \13705    CLASS *AA = nullptr;                                                       \13706    switch (IRP.getPositionKind()) {                                           \13707      SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid")                             \13708      SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function)                     \13709      SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite)                    \13710      SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating)                        \13711      SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument)                     \13712      SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned)                     \13713      SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned)   \13714      SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument)   \13715    }                                                                          \13716    return *AA;                                                                \13717  }13718 13719#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)            \13720  CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) {      \13721    CLASS *AA = nullptr;                                                       \13722    switch (IRP.getPositionKind()) {                                           \13723      SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid")                             \13724      SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument")                           \13725      SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating")                              \13726      SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned")                           \13727      SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned")       \13728      SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument")       \13729      SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site")                         \13730      SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function)                     \13731    }                                                                          \13732    return *AA;                                                                \13733  }13734 13735#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)                  \13736  CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) {      \13737    CLASS *AA = nullptr;                                                       \13738    switch (IRP.getPositionKind()) {                                           \13739      SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid")                             \13740      SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned")                           \13741      SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function)                     \13742      SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite)                    \13743      SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating)                        \13744      SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument)                     \13745      SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned)   \13746      SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument)   \13747    }                                                                          \13748    return *AA;                                                                \13749  }13750 13751CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoUnwind)13752CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoSync)13753CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoRecurse)13754CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAWillReturn)13755CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoReturn)13756CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAMemoryLocation)13757CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AACallEdges)13758CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAssumptionInfo)13759CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAMustProgress)13760 13761CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANonNull)13762CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoAlias)13763CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPrivatizablePtr)13764CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AADereferenceable)13765CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAlign)13766CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAInstanceInfo)13767CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoCapture)13768CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAValueConstantRange)13769CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPotentialConstantValues)13770CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPotentialValues)13771CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoUndef)13772CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoFPClass)13773CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPointerInfo)13774CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAInvariantLoadPointer)13775CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAddressSpace)13776CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoAliasAddrSpace)13777CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAllocationInfo)13778 13779CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAValueSimplify)13780CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAIsDead)13781CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoFree)13782CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAUnderlyingObjects)13783 13784CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(IRP_CALL_SITE, CallSite,13785                                           AAIndirectCallInfo)13786CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(IRP_FLOAT, Floating,13787                                           AAGlobalValueInfo)13788 13789CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAHeapToStack)13790CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAUndefinedBehavior)13791CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANonConvergent)13792CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAIntraFnReachability)13793CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAInterFnReachability)13794CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AADenormalFPMath)13795 13796CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAMemoryBehavior)13797 13798#undef CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION13799#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION13800#undef CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION13801#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION13802#undef CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION13803#undef CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION13804#undef SWITCH_PK_CREATE13805#undef SWITCH_PK_INV13806