//===-- Analysis.cpp - CodeGen LLVM IR Analysis Utilities -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines several CodeGen-specific LLVM IR analysis utilities.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/Analysis.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"

using namespace llvm;

/// Compute the linearized index of a member in a nested aggregate/struct/array
/// by recursing and accumulating CurIndex as long as there are indices in the
/// index list.
unsigned llvm::ComputeLinearIndex(Type *Ty,
                                  const unsigned *Indices,
                                  const unsigned *IndicesEnd,
                                  unsigned CurIndex) {
  // Base case: We're done.
  if (Indices && Indices == IndicesEnd)
    return CurIndex;

  // Given a struct type, recursively traverse the elements.
  if (StructType *STy = dyn_cast<StructType>(Ty)) {
    for (auto I : llvm::enumerate(STy->elements())) {
      Type *ET = I.value();
      if (Indices && *Indices == I.index())
        return ComputeLinearIndex(ET, Indices + 1, IndicesEnd, CurIndex);
      CurIndex = ComputeLinearIndex(ET, nullptr, nullptr, CurIndex);
    }
    assert(!Indices && "Unexpected out of bound");
    return CurIndex;
  }
  // Given an array type, recursively traverse the elements.
  else if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
    Type *EltTy = ATy->getElementType();
    unsigned NumElts = ATy->getNumElements();
    // Compute the Linear offset when jumping one element of the array
    unsigned EltLinearOffset = ComputeLinearIndex(EltTy, nullptr, nullptr, 0);
    if (Indices) {
      assert(*Indices < NumElts && "Unexpected out of bound");
      // If the indice is inside the array, compute the index to the requested
      // elt and recurse inside the element with the end of the indices list
      CurIndex += EltLinearOffset* *Indices;
      return ComputeLinearIndex(EltTy, Indices+1, IndicesEnd, CurIndex);
    }
    CurIndex += EltLinearOffset*NumElts;
    return CurIndex;
  }
  // We haven't found the type we're looking for, so keep searching.
  return CurIndex + 1;
}

void llvm::ComputeValueTypes(const DataLayout &DL, Type *Ty,
                             SmallVectorImpl<Type *> &Types,
                             SmallVectorImpl<TypeSize> *Offsets,
                             TypeSize StartingOffset) {
  assert((Ty->isScalableTy() == StartingOffset.isScalable() ||
          StartingOffset.isZero()) &&
         "Offset/TypeSize mismatch!");
  // Given a struct type, recursively traverse the elements.
  if (StructType *STy = dyn_cast<StructType>(Ty)) {
    // If the Offsets aren't needed, don't query the struct layout. This allows
    // us to support structs with scalable vectors for operations that don't
    // need offsets.
    const StructLayout *SL = Offsets ? DL.getStructLayout(STy) : nullptr;
    for (StructType::element_iterator EB = STy->element_begin(), EI = EB,
                                      EE = STy->element_end();
         EI != EE; ++EI) {
      // Don't compute the element offset if we didn't get a StructLayout above.
      TypeSize EltOffset =
          SL ? SL->getElementOffset(EI - EB) : TypeSize::getZero();
      ComputeValueTypes(DL, *EI, Types, Offsets, StartingOffset + EltOffset);
    }
    return;
  }
  // Given an array type, recursively traverse the elements.
  if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
    Type *EltTy = ATy->getElementType();
    TypeSize EltSize = DL.getTypeAllocSize(EltTy);
    for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i)
      ComputeValueTypes(DL, EltTy, Types, Offsets,
                        StartingOffset + i * EltSize);
    return;
  }
  // Interpret void as zero return values.
  if (Ty->isVoidTy())
    return;
  Types.push_back(Ty);
  if (Offsets)
    Offsets->push_back(StartingOffset);
}

/// ComputeValueVTs - Given an LLVM IR type, compute a sequence of
/// EVTs that represent all the individual underlying
/// non-aggregate types that comprise it.
///
/// If Offsets is non-null, it points to a vector to be filled in
/// with the in-memory offsets of each of the individual values.
///
void llvm::ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL,
                           Type *Ty, SmallVectorImpl<EVT> &ValueVTs,
                           SmallVectorImpl<EVT> *MemVTs,
                           SmallVectorImpl<TypeSize> *Offsets,
                           TypeSize StartingOffset) {
  SmallVector<Type *> Types;
  ComputeValueTypes(DL, Ty, Types, Offsets, StartingOffset);
  ValueVTs.reserve(Types.size());
  if (MemVTs)
    MemVTs->reserve(Types.size());
  for (Type *Ty : Types) {
    ValueVTs.push_back(TLI.getValueType(DL, Ty));
    if (MemVTs)
      MemVTs->push_back(TLI.getMemValueType(DL, Ty));
  }
}

void llvm::ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL,
                           Type *Ty, SmallVectorImpl<EVT> &ValueVTs,
                           SmallVectorImpl<EVT> *MemVTs,
                           SmallVectorImpl<uint64_t> *FixedOffsets,
                           uint64_t StartingOffset) {
  TypeSize Offset = TypeSize::getFixed(StartingOffset);
  if (FixedOffsets) {
    SmallVector<TypeSize, 4> Offsets;
    ComputeValueVTs(TLI, DL, Ty, ValueVTs, MemVTs, &Offsets, Offset);
    FixedOffsets->reserve(Offsets.size());
    for (TypeSize Offset : Offsets)
      FixedOffsets->push_back(Offset.getFixedValue());
  } else {
    ComputeValueVTs(TLI, DL, Ty, ValueVTs, MemVTs, nullptr, Offset);
  }
}

void llvm::computeValueLLTs(const DataLayout &DL, Type &Ty,
                            SmallVectorImpl<LLT> &ValueLLTs,
                            SmallVectorImpl<TypeSize> *Offsets,
                            TypeSize StartingOffset) {
  SmallVector<Type *> ValTys;
  ComputeValueTypes(DL, &Ty, ValTys, Offsets, StartingOffset);
  ValueLLTs.reserve(ValTys.size());
  for (Type *ValTy : ValTys)
    ValueLLTs.push_back(getLLTForType(*ValTy, DL));
}

void llvm::computeValueLLTs(const DataLayout &DL, Type &Ty,
                            SmallVectorImpl<LLT> &ValueLLTs,
                            SmallVectorImpl<uint64_t> *FixedOffsets,
                            uint64_t FixedStartingOffset) {
  TypeSize StartingOffset = TypeSize::getFixed(FixedStartingOffset);
  if (FixedOffsets) {
    SmallVector<TypeSize, 4> Offsets;
    computeValueLLTs(DL, Ty, ValueLLTs, &Offsets, StartingOffset);
    FixedOffsets->reserve(Offsets.size());
    for (TypeSize Offset : Offsets)
      FixedOffsets->push_back(Offset.getFixedValue());
  } else {
    computeValueLLTs(DL, Ty, ValueLLTs, nullptr, StartingOffset);
  }
}

/// ExtractTypeInfo - Returns the type info, possibly bitcast, encoded in V.
GlobalValue *llvm::ExtractTypeInfo(Value *V) {
  V = V->stripPointerCasts();
  GlobalValue *GV = dyn_cast<GlobalValue>(V);
  GlobalVariable *Var = dyn_cast<GlobalVariable>(V);

  if (Var && Var->getName() == "llvm.eh.catch.all.value") {
    assert(Var->hasInitializer() &&
           "The EH catch-all value must have an initializer");
    Value *Init = Var->getInitializer();
    GV = dyn_cast<GlobalValue>(Init);
    if (!GV) V = cast<ConstantPointerNull>(Init);
  }

  assert((GV || isa<ConstantPointerNull>(V)) &&
         "TypeInfo must be a global variable or NULL");
  return GV;
}

bool llvm::isExceptionPointerAndSelectorType(Type *Ty) {
  auto *STy = dyn_cast<StructType>(Ty);
  if (!STy || STy->getNumElements() != 2)
    return false;
  Type *ExnTy = STy->getElementType(0);
  return (ExnTy->isPointerTy() || ExnTy->isIntegerTy()) &&
         STy->getElementType(1)->isIntegerTy();
}

/// getFCmpCondCode - Return the ISD condition code corresponding to
/// the given LLVM IR floating-point condition code.  This includes
/// consideration of global floating-point math flags.
///
ISD::CondCode llvm::getFCmpCondCode(FCmpInst::Predicate Pred) {
  switch (Pred) {
  case FCmpInst::FCMP_FALSE: return ISD::SETFALSE;
  case FCmpInst::FCMP_OEQ:   return ISD::SETOEQ;
  case FCmpInst::FCMP_OGT:   return ISD::SETOGT;
  case FCmpInst::FCMP_OGE:   return ISD::SETOGE;
  case FCmpInst::FCMP_OLT:   return ISD::SETOLT;
  case FCmpInst::FCMP_OLE:   return ISD::SETOLE;
  case FCmpInst::FCMP_ONE:   return ISD::SETONE;
  case FCmpInst::FCMP_ORD:   return ISD::SETO;
  case FCmpInst::FCMP_UNO:   return ISD::SETUO;
  case FCmpInst::FCMP_UEQ:   return ISD::SETUEQ;
  case FCmpInst::FCMP_UGT:   return ISD::SETUGT;
  case FCmpInst::FCMP_UGE:   return ISD::SETUGE;
  case FCmpInst::FCMP_ULT:   return ISD::SETULT;
  case FCmpInst::FCMP_ULE:   return ISD::SETULE;
  case FCmpInst::FCMP_UNE:   return ISD::SETUNE;
  case FCmpInst::FCMP_TRUE:  return ISD::SETTRUE;
  default: llvm_unreachable("Invalid FCmp predicate opcode!");
  }
}

ISD::CondCode llvm::getFCmpCodeWithoutNaN(ISD::CondCode CC) {
  switch (CC) {
    case ISD::SETOEQ: case ISD::SETUEQ: return ISD::SETEQ;
    case ISD::SETONE: case ISD::SETUNE: return ISD::SETNE;
    case ISD::SETOLT: case ISD::SETULT: return ISD::SETLT;
    case ISD::SETOLE: case ISD::SETULE: return ISD::SETLE;
    case ISD::SETOGT: case ISD::SETUGT: return ISD::SETGT;
    case ISD::SETOGE: case ISD::SETUGE: return ISD::SETGE;
    default: return CC;
  }
}

ISD::CondCode llvm::getICmpCondCode(ICmpInst::Predicate Pred) {
  switch (Pred) {
  case ICmpInst::ICMP_EQ:  return ISD::SETEQ;
  case ICmpInst::ICMP_NE:  return ISD::SETNE;
  case ICmpInst::ICMP_SLE: return ISD::SETLE;
  case ICmpInst::ICMP_ULE: return ISD::SETULE;
  case ICmpInst::ICMP_SGE: return ISD::SETGE;
  case ICmpInst::ICMP_UGE: return ISD::SETUGE;
  case ICmpInst::ICMP_SLT: return ISD::SETLT;
  case ICmpInst::ICMP_ULT: return ISD::SETULT;
  case ICmpInst::ICMP_SGT: return ISD::SETGT;
  case ICmpInst::ICMP_UGT: return ISD::SETUGT;
  default:
    llvm_unreachable("Invalid ICmp predicate opcode!");
  }
}

ICmpInst::Predicate llvm::getICmpCondCode(ISD::CondCode Pred) {
  switch (Pred) {
  case ISD::SETEQ:
    return ICmpInst::ICMP_EQ;
  case ISD::SETNE:
    return ICmpInst::ICMP_NE;
  case ISD::SETLE:
    return ICmpInst::ICMP_SLE;
  case ISD::SETULE:
    return ICmpInst::ICMP_ULE;
  case ISD::SETGE:
    return ICmpInst::ICMP_SGE;
  case ISD::SETUGE:
    return ICmpInst::ICMP_UGE;
  case ISD::SETLT:
    return ICmpInst::ICMP_SLT;
  case ISD::SETULT:
    return ICmpInst::ICMP_ULT;
  case ISD::SETGT:
    return ICmpInst::ICMP_SGT;
  case ISD::SETUGT:
    return ICmpInst::ICMP_UGT;
  default:
    llvm_unreachable("Invalid ISD integer condition code!");
  }
}

static bool isNoopBitcast(Type *T1, Type *T2,
                          const TargetLoweringBase& TLI) {
  return T1 == T2 || (T1->isPointerTy() && T2->isPointerTy()) ||
         (isa<VectorType>(T1) && isa<VectorType>(T2) &&
          TLI.isTypeLegal(EVT::getEVT(T1)) && TLI.isTypeLegal(EVT::getEVT(T2)));
}

/// Look through operations that will be free to find the earliest source of
/// this value.
///
/// @param ValLoc If V has aggregate type, we will be interested in a particular
/// scalar component. This records its address; the reverse of this list gives a
/// sequence of indices appropriate for an extractvalue to locate the important
/// value. This value is updated during the function and on exit will indicate
/// similar information for the Value returned.
///
/// @param DataBits If this function looks through truncate instructions, this
/// will record the smallest size attained.
static const Value *getNoopInput(const Value *V,
                                 SmallVectorImpl<unsigned> &ValLoc,
                                 unsigned &DataBits,
                                 const TargetLoweringBase &TLI,
                                 const DataLayout &DL) {
  while (true) {
    // Try to look through V1; if V1 is not an instruction, it can't be looked
    // through.
    const Instruction *I = dyn_cast<Instruction>(V);
    if (!I || I->getNumOperands() == 0) return V;
    const Value *NoopInput = nullptr;

    Value *Op = I->getOperand(0);
    if (isa<BitCastInst>(I)) {
      // Look through truly no-op bitcasts.
      if (isNoopBitcast(Op->getType(), I->getType(), TLI))
        NoopInput = Op;
    } else if (isa<GetElementPtrInst>(I)) {
      // Look through getelementptr
      if (cast<GetElementPtrInst>(I)->hasAllZeroIndices())
        NoopInput = Op;
    } else if (isa<IntToPtrInst>(I)) {
      // Look through inttoptr.
      // Make sure this isn't a truncating or extending cast.  We could
      // support this eventually, but don't bother for now.
      if (!isa<VectorType>(I->getType()) &&
          DL.getPointerSizeInBits() ==
              cast<IntegerType>(Op->getType())->getBitWidth())
        NoopInput = Op;
    } else if (isa<PtrToIntInst>(I)) {
      // Look through ptrtoint.
      // Make sure this isn't a truncating or extending cast.  We could
      // support this eventually, but don't bother for now.
      if (!isa<VectorType>(I->getType()) &&
          DL.getPointerSizeInBits() ==
              cast<IntegerType>(I->getType())->getBitWidth())
        NoopInput = Op;
    } else if (isa<TruncInst>(I) &&
               TLI.allowTruncateForTailCall(Op->getType(), I->getType())) {
      DataBits =
          std::min((uint64_t)DataBits,
                   I->getType()->getPrimitiveSizeInBits().getFixedValue());
      NoopInput = Op;
    } else if (auto *CB = dyn_cast<CallBase>(I)) {
      const Value *ReturnedOp = CB->getReturnedArgOperand();
      if (ReturnedOp && isNoopBitcast(ReturnedOp->getType(), I->getType(), TLI))
        NoopInput = ReturnedOp;
    } else if (const InsertValueInst *IVI = dyn_cast<InsertValueInst>(V)) {
      // Value may come from either the aggregate or the scalar
      ArrayRef<unsigned> InsertLoc = IVI->getIndices();
      if (ValLoc.size() >= InsertLoc.size() &&
          std::equal(InsertLoc.begin(), InsertLoc.end(), ValLoc.rbegin())) {
        // The type being inserted is a nested sub-type of the aggregate; we
        // have to remove those initial indices to get the location we're
        // interested in for the operand.
        ValLoc.resize(ValLoc.size() - InsertLoc.size());
        NoopInput = IVI->getInsertedValueOperand();
      } else {
        // The struct we're inserting into has the value we're interested in, no
        // change of address.
        NoopInput = Op;
      }
    } else if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(V)) {
      // The part we're interested in will inevitably be some sub-section of the
      // previous aggregate. Combine the two paths to obtain the true address of
      // our element.
      ArrayRef<unsigned> ExtractLoc = EVI->getIndices();
      ValLoc.append(ExtractLoc.rbegin(), ExtractLoc.rend());
      NoopInput = Op;
    }
    // Terminate if we couldn't find anything to look through.
    if (!NoopInput)
      return V;

    V = NoopInput;
  }
}

/// Return true if this scalar return value only has bits discarded on its path
/// from the "tail call" to the "ret". This includes the obvious noop
/// instructions handled by getNoopInput above as well as free truncations (or
/// extensions prior to the call).
static bool slotOnlyDiscardsData(const Value *RetVal, const Value *CallVal,
                                 SmallVectorImpl<unsigned> &RetIndices,
                                 SmallVectorImpl<unsigned> &CallIndices,
                                 bool AllowDifferingSizes,
                                 const TargetLoweringBase &TLI,
                                 const DataLayout &DL) {

  // Trace the sub-value needed by the return value as far back up the graph as
  // possible, in the hope that it will intersect with the value produced by the
  // call. In the simple case with no "returned" attribute, the hope is actually
  // that we end up back at the tail call instruction itself.
  unsigned BitsRequired = UINT_MAX;
  RetVal = getNoopInput(RetVal, RetIndices, BitsRequired, TLI, DL);

  // If this slot in the value returned is undef, it doesn't matter what the
  // call puts there, it'll be fine.
  if (isa<UndefValue>(RetVal))
    return true;

  // Now do a similar search up through the graph to find where the value
  // actually returned by the "tail call" comes from. In the simple case without
  // a "returned" attribute, the search will be blocked immediately and the loop
  // a Noop.
  unsigned BitsProvided = UINT_MAX;
  CallVal = getNoopInput(CallVal, CallIndices, BitsProvided, TLI, DL);

  // There's no hope if we can't actually trace them to (the same part of!) the
  // same value.
  if (CallVal != RetVal || CallIndices != RetIndices)
    return false;

  // However, intervening truncates may have made the call non-tail. Make sure
  // all the bits that are needed by the "ret" have been provided by the "tail
  // call". FIXME: with sufficiently cunning bit-tracking, we could look through
  // extensions too.
  if (BitsProvided < BitsRequired ||
      (!AllowDifferingSizes && BitsProvided != BitsRequired))
    return false;

  return true;
}

/// For an aggregate type, determine whether a given index is within bounds or
/// not.
static bool indexReallyValid(Type *T, unsigned Idx) {
  if (ArrayType *AT = dyn_cast<ArrayType>(T))
    return Idx < AT->getNumElements();

  return Idx < cast<StructType>(T)->getNumElements();
}

/// Move the given iterators to the next leaf type in depth first traversal.
///
/// Performs a depth-first traversal of the type as specified by its arguments,
/// stopping at the next leaf node (which may be a legitimate scalar type or an
/// empty struct or array).
///
/// @param SubTypes List of the partial components making up the type from
/// outermost to innermost non-empty aggregate. The element currently
/// represented is SubTypes.back()->getTypeAtIndex(Path.back() - 1).
///
/// @param Path Set of extractvalue indices leading from the outermost type
/// (SubTypes[0]) to the leaf node currently represented.
///
/// @returns true if a new type was found, false otherwise. Calling this
/// function again on a finished iterator will repeatedly return
/// false. SubTypes.back()->getTypeAtIndex(Path.back()) is either an empty
/// aggregate or a non-aggregate
static bool advanceToNextLeafType(SmallVectorImpl<Type *> &SubTypes,
                                  SmallVectorImpl<unsigned> &Path) {
  // First march back up the tree until we can successfully increment one of the
  // coordinates in Path.
  while (!Path.empty() && !indexReallyValid(SubTypes.back(), Path.back() + 1)) {
    Path.pop_back();
    SubTypes.pop_back();
  }

  // If we reached the top, then the iterator is done.
  if (Path.empty())
    return false;

  // We know there's *some* valid leaf now, so march back down the tree picking
  // out the left-most element at each node.
  ++Path.back();
  Type *DeeperType =
      ExtractValueInst::getIndexedType(SubTypes.back(), Path.back());
  while (DeeperType->isAggregateType()) {
    if (!indexReallyValid(DeeperType, 0))
      return true;

    SubTypes.push_back(DeeperType);
    Path.push_back(0);

    DeeperType = ExtractValueInst::getIndexedType(DeeperType, 0);
  }

  return true;
}

/// Find the first non-empty, scalar-like type in Next and setup the iterator
/// components.
///
/// Assuming Next is an aggregate of some kind, this function will traverse the
/// tree from left to right (i.e. depth-first) looking for the first
/// non-aggregate type which will play a role in function return.
///
/// For example, if Next was {[0 x i64], {{}, i32, {}}, i32} then we would setup
/// Path as [1, 1] and SubTypes as [Next, {{}, i32, {}}] to represent the first
/// i32 in that type.
static bool firstRealType(Type *Next, SmallVectorImpl<Type *> &SubTypes,
                          SmallVectorImpl<unsigned> &Path) {
  // First initialise the iterator components to the first "leaf" node
  // (i.e. node with no valid sub-type at any index, so {} does count as a leaf
  // despite nominally being an aggregate).
  while (Type *FirstInner = ExtractValueInst::getIndexedType(Next, 0)) {
    SubTypes.push_back(Next);
    Path.push_back(0);
    Next = FirstInner;
  }

  // If there's no Path now, Next was originally scalar already (or empty
  // leaf). We're done.
  if (Path.empty())
    return true;

  // Otherwise, use normal iteration to keep looking through the tree until we
  // find a non-aggregate type.
  while (ExtractValueInst::getIndexedType(SubTypes.back(), Path.back())
             ->isAggregateType()) {
    if (!advanceToNextLeafType(SubTypes, Path))
      return false;
  }

  return true;
}

/// Set the iterator data-structures to the next non-empty, non-aggregate
/// subtype.
static bool nextRealType(SmallVectorImpl<Type *> &SubTypes,
                         SmallVectorImpl<unsigned> &Path) {
  do {
    if (!advanceToNextLeafType(SubTypes, Path))
      return false;

    assert(!Path.empty() && "found a leaf but didn't set the path?");
  } while (ExtractValueInst::getIndexedType(SubTypes.back(), Path.back())
               ->isAggregateType());

  return true;
}

/// Resolve the DWARF version the way DwarfDebug does.
/// FIXME: Share this resolution with DwarfDebug's, which has to match.
static unsigned getDwarfVersion(const MachineFunction &MF) {
  unsigned DwarfVersion = MF.getTarget().Options.MCOptions.DwarfVersion;
  if (!DwarfVersion)
    DwarfVersion = MF.getFunction().getParent()->getDwarfVersion();
  if (!DwarfVersion)
    DwarfVersion = dwarf::DWARF_VERSION;
  return DwarfVersion;
}

bool llvm::canDescribeGlobalAddressInDebugInfo(const GlobalValue *GV,
                                               const MachineFunction &MF) {
  // Only definitions have an address a symbol reference can name.
  if (GV->isDeclarationForLinker())
    return false;
  // A thread-local's address is not known until it is resolved against a
  // thread's storage, which a plain symbol reference cannot express.
  if (GV->isThreadLocal())
    return false;
  // Computing the address of a dllimport'd entity requires a load from the
  // import address table, which a static symbol reference cannot express.
  if (GV->hasDLLImportStorageClass())
    return false;
  // An ifunc resolves to whatever its resolver returns at load time, so the
  // symbol's own address is not the value of the pointer.
  if (isa<GlobalIFunc>(GV))
    return false;

  const Module &M = *MF.getFunction().getParent();
  const TargetMachine &TM = MF.getTarget();

  // AsmPrinter may fold a GOT equivalent (an unnamed private constant
  // holding the address of another global) into a GOT-relative
  // relocation at its use and then never define the symbol. Whether
  // that happens is only known once every use has been emitted, and a
  // debug info reference does not count as a use, so it is not safe
  // return true here.
  if (TM.getObjFileLowering()->supportIndirectSymViaGOTPCRel())
    if (const auto *GVar = dyn_cast<GlobalVariable>(GV))
      if (GVar->hasGlobalUnnamedAddr() && GVar->isConstant() &&
          GVar->hasInitializer() && GVar->isDiscardableIfUnused() &&
          isa<GlobalValue>(GVar->getOperand(0)))
        return false;

  // CodeView has no way to name a symbol in a local variable's location, so
  // choosing one here would leave the variable with no location at all.
  if (M.getCodeViewFlag())
    return false;

  // Saying that the variable holds this address, rather than that it lives at
  // it, needs DW_OP_stack_value, which DWARF 4 introduced. Nothing older can
  // express the difference, so leave those versions to describe the variable by
  // wherever the address is materialized instead. DwarfExpression refuses the
  // same versions; deciding here only picks the better of the two fallbacks,
  // while a materialized location is still available to fall back on.
  if (getDwarfVersion(MF) < 4)
    return false;

  // On some targets a global does not live at its symbol's address; a base
  // known only at run time has to be added to it. DwarfCompileUnit builds
  // those addends for global variables, but they need a relocation, which a
  // location list cannot carry, so a local pointing at such a global has to
  // keep being described by whatever register holds the computed address.
  if (M.getTargetTriple().isWasm() && TM.getRelocationModel() == Reloc::PIC_)
    return false;
  if (TM.getRelocationModel() == Reloc::RWPI ||
      TM.getRelocationModel() == Reloc::ROPI_RWPI) {
    // Only writable globals are addressed relative to the static base;
    // read-only ones keep an absolute address. An alias may name either, so
    // give up rather than chase it.
    const auto *GO = dyn_cast<GlobalObject>(GV);
    if (!GO || !TM.getObjFileLowering()->getKindForGlobal(GO, TM).isReadOnly())
      return false;
  }

  return true;
}

const GlobalValue *
llvm::getDescribableGlobalAddress(const Constant *C, int64_t &Offset,
                                  const MachineFunction &MF) {
  Offset = 0;
  if (!C->getType()->isPointerTy())
    return nullptr;

  // Non-inbounds offsets are stripped as well, which is the default. The
  // inbounds flag constrains what the program may do with the pointer, not
  // what its value is, and describing an address needs only the value.
  int64_t GVOffset;
  const auto *GV = dyn_cast<GlobalValue>(
      GetPointerBaseWithConstantOffset(C, GVOffset, MF.getDataLayout()));
  if (!GV || !canDescribeGlobalAddressInDebugInfo(GV, MF))
    return nullptr;

  Offset = GVOffset;
  return GV;
}

bool llvm::canDescribeGlobalAddressInLocationList(const MachineFunction &MF) {
  // A location list is emitted as plain bytes, which cannot carry the
  // relocation a DW_OP_addr needs, so there the address has to be an index into
  // the address pool. Before DWARF 5 that pool only exists under split DWARF.
  return getDwarfVersion(MF) >= 5 ||
         !MF.getTarget().Options.MCOptions.SplitDwarfFile.empty();
}

/// Test if the given instruction is in a position to be optimized
/// with a tail-call. This roughly means that it's in a block with
/// a return and there's nothing that needs to be scheduled
/// between it and the return.
///
/// This function only tests target-independent requirements.
bool llvm::isInTailCallPosition(const CallBase &Call, const TargetMachine &TM,
                                bool ReturnsFirstArg) {
  const BasicBlock *ExitBB = Call.getParent();
  const Instruction *Term = ExitBB->getTerminator();
  const ReturnInst *Ret = dyn_cast<ReturnInst>(Term);

  // The block must end in a return statement or unreachable.
  //
  // FIXME: Decline tailcall if it's not guaranteed and if the block ends in
  // an unreachable, for now. The way tailcall optimization is currently
  // implemented means it will add an epilogue followed by a jump. That is
  // not profitable. Also, if the callee is a special function (e.g.
  // longjmp on x86), it can end up causing miscompilation that has not
  // been fully understood.
  if (!Ret && ((!TM.Options.GuaranteedTailCallOpt &&
                Call.getCallingConv() != CallingConv::Tail &&
                Call.getCallingConv() != CallingConv::SwiftTail) ||
               !isa<UnreachableInst>(Term)))
    return false;

  // If I will have a chain, make sure no other instruction that will have a
  // chain interposes between I and the return.
  // Check for all calls including speculatable functions.
  for (BasicBlock::const_iterator BBI = std::prev(ExitBB->end(), 2);; --BBI) {
    if (&*BBI == &Call)
      break;
    // Debug info intrinsics do not get in the way of tail call optimization.
    // Pseudo probe intrinsics do not block tail call optimization either.
    if (BBI->isDebugOrPseudoInst())
      continue;
    // A lifetime end, assume or noalias.decl intrinsic should not stop tail
    // call optimization.
    if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(BBI))
      if (II->getIntrinsicID() == Intrinsic::lifetime_end ||
          II->getIntrinsicID() == Intrinsic::assume ||
          II->getIntrinsicID() == Intrinsic::experimental_noalias_scope_decl ||
          II->getIntrinsicID() == Intrinsic::fake_use)
        continue;
    if (BBI->mayHaveSideEffects() || BBI->mayReadFromMemory() ||
        !isSafeToSpeculativelyExecute(&*BBI))
      return false;
  }

  const Function *F = ExitBB->getParent();
  return returnTypeIsEligibleForTailCall(
      F, &Call, Ret, *TM.getSubtargetImpl(*F)->getTargetLowering(),
      ReturnsFirstArg);
}

bool llvm::attributesPermitTailCall(const Function *F, const Instruction *I,
                                    const ReturnInst *Ret,
                                    const TargetLoweringBase &TLI,
                                    bool *AllowDifferingSizes) {
  // ADS may be null, so don't write to it directly.
  bool DummyADS;
  bool &ADS = AllowDifferingSizes ? *AllowDifferingSizes : DummyADS;
  ADS = true;

  AttrBuilder CallerAttrs(F->getContext(), F->getAttributes().getRetAttrs());
  AttrBuilder CalleeAttrs(F->getContext(),
                          cast<CallInst>(I)->getAttributes().getRetAttrs());

  // Following attributes are completely benign as far as calling convention
  // goes, they shouldn't affect whether the call is a tail call.
  for (const auto &Attr : {Attribute::Alignment, Attribute::Dereferenceable,
                           Attribute::DereferenceableOrNull, Attribute::NoAlias,
                           Attribute::NonNull, Attribute::NoUndef,
                           Attribute::Range, Attribute::NoFPClass}) {
    CallerAttrs.removeAttribute(Attr);
    CalleeAttrs.removeAttribute(Attr);
  }

  if (CallerAttrs.contains(Attribute::ZExt)) {
    if (!CalleeAttrs.contains(Attribute::ZExt))
      return false;

    ADS = false;
    CallerAttrs.removeAttribute(Attribute::ZExt);
    CalleeAttrs.removeAttribute(Attribute::ZExt);
  } else if (CallerAttrs.contains(Attribute::SExt)) {
    if (!CalleeAttrs.contains(Attribute::SExt))
      return false;

    ADS = false;
    CallerAttrs.removeAttribute(Attribute::SExt);
    CalleeAttrs.removeAttribute(Attribute::SExt);
  }

  // Drop sext and zext return attributes if the result is not used.
  // This enables tail calls for code like:
  //
  // define void @caller() {
  // entry:
  //   %unused_result = tail call zeroext i1 @callee()
  //   br label %retlabel
  // retlabel:
  //   ret void
  // }
  if (I->use_empty()) {
    CalleeAttrs.removeAttribute(Attribute::SExt);
    CalleeAttrs.removeAttribute(Attribute::ZExt);
  }

  // If they're still different, there's some facet we don't understand
  // (currently only "inreg", but in future who knows). It may be OK but the
  // only safe option is to reject the tail call.
  return CallerAttrs == CalleeAttrs;
}

bool llvm::returnTypeIsEligibleForTailCall(const Function *F,
                                           const Instruction *I,
                                           const ReturnInst *Ret,
                                           const TargetLoweringBase &TLI,
                                           bool ReturnsFirstArg) {
  // If the block ends with a void return or unreachable, it doesn't matter
  // what the call's return type is.
  if (!Ret || Ret->getNumOperands() == 0) return true;

  // If the return value is undef, it doesn't matter what the call's
  // return type is.
  if (isa<UndefValue>(Ret->getOperand(0))) return true;

  // Make sure the attributes attached to each return are compatible.
  bool AllowDifferingSizes;
  if (!attributesPermitTailCall(F, I, Ret, TLI, &AllowDifferingSizes))
    return false;

  // If the return value is the first argument of the call.
  if (ReturnsFirstArg)
    return true;

  const Value *RetVal = Ret->getOperand(0), *CallVal = I;
  SmallVector<unsigned, 4> RetPath, CallPath;
  SmallVector<Type *, 4> RetSubTypes, CallSubTypes;

  bool RetEmpty = !firstRealType(RetVal->getType(), RetSubTypes, RetPath);
  bool CallEmpty = !firstRealType(CallVal->getType(), CallSubTypes, CallPath);

  // Nothing's actually returned, it doesn't matter what the callee put there
  // it's a valid tail call.
  if (RetEmpty)
    return true;

  // Iterate pairwise through each of the value types making up the tail call
  // and the corresponding return. For each one we want to know whether it's
  // essentially going directly from the tail call to the ret, via operations
  // that end up not generating any code.
  //
  // We allow a certain amount of covariance here. For example it's permitted
  // for the tail call to define more bits than the ret actually cares about
  // (e.g. via a truncate).
  do {
    if (CallEmpty) {
      // We've exhausted the values produced by the tail call instruction, the
      // rest are essentially undef. The type doesn't really matter, but we need
      // *something*.
      Type *SlotType =
          ExtractValueInst::getIndexedType(RetSubTypes.back(), RetPath.back());
      CallVal = UndefValue::get(SlotType);
    }

    // The manipulations performed when we're looking through an insertvalue or
    // an extractvalue would happen at the front of the RetPath list, so since
    // we have to copy it anyway it's more efficient to create a reversed copy.
    SmallVector<unsigned, 4> TmpRetPath(llvm::reverse(RetPath));
    SmallVector<unsigned, 4> TmpCallPath(llvm::reverse(CallPath));

    // Finally, we can check whether the value produced by the tail call at this
    // index is compatible with the value we return.
    if (!slotOnlyDiscardsData(RetVal, CallVal, TmpRetPath, TmpCallPath,
                              AllowDifferingSizes, TLI,
                              F->getDataLayout()))
      return false;

    CallEmpty  = !nextRealType(CallSubTypes, CallPath);
  } while(nextRealType(RetSubTypes, RetPath));

  return true;
}

bool llvm::funcReturnsFirstArgOfCall(const CallInst &CI) {
  const ReturnInst *Ret = dyn_cast<ReturnInst>(CI.getParent()->getTerminator());
  Value *RetVal = Ret ? Ret->getReturnValue() : nullptr;
  bool ReturnsFirstArg = false;
  if (RetVal && ((RetVal == CI.getArgOperand(0))))
    ReturnsFirstArg = true;
  return ReturnsFirstArg;
}

static void collectEHScopeMembers(
    DenseMap<const MachineBasicBlock *, int> &EHScopeMembership, int EHScope,
    const MachineBasicBlock *MBB) {
  SmallVector<const MachineBasicBlock *, 16> Worklist = {MBB};
  while (!Worklist.empty()) {
    const MachineBasicBlock *Visiting = Worklist.pop_back_val();
    // Don't follow blocks which start new scopes.
    if (Visiting->isEHPad() && Visiting != MBB)
      continue;

    // Add this MBB to our scope.
    auto P = EHScopeMembership.insert(std::make_pair(Visiting, EHScope));

    // Don't revisit blocks.
    if (!P.second) {
      assert(P.first->second == EHScope && "MBB is part of two scopes!");
      continue;
    }

    // Returns are boundaries where scope transfer can occur, don't follow
    // successors.
    if (Visiting->isEHScopeReturnBlock())
      continue;

    append_range(Worklist, Visiting->successors());
  }
}

DenseMap<const MachineBasicBlock *, int>
llvm::getEHScopeMembership(const MachineFunction &MF) {
  DenseMap<const MachineBasicBlock *, int> EHScopeMembership;

  // We don't have anything to do if there aren't any EH pads.
  if (!MF.hasEHScopes())
    return EHScopeMembership;

  int EntryBBNumber = MF.front().getNumber();
  bool IsSEH = isAsynchronousEHPersonality(
      classifyEHPersonality(MF.getFunction().getPersonalityFn()));

  const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
  SmallVector<const MachineBasicBlock *, 16> EHScopeBlocks;
  SmallVector<const MachineBasicBlock *, 16> UnreachableBlocks;
  SmallVector<const MachineBasicBlock *, 16> SEHCatchPads;
  SmallVector<std::pair<const MachineBasicBlock *, int>, 16> CatchRetSuccessors;
  for (const MachineBasicBlock &MBB : MF) {
    if (MBB.isEHScopeEntry()) {
      EHScopeBlocks.push_back(&MBB);
    } else if (IsSEH && MBB.isEHPad()) {
      SEHCatchPads.push_back(&MBB);
    } else if (MBB.pred_empty()) {
      UnreachableBlocks.push_back(&MBB);
    }

    MachineBasicBlock::const_iterator MBBI = MBB.getFirstTerminator();

    // CatchPads are not scopes for SEH so do not consider CatchRet to
    // transfer control to another scope.
    if (MBBI == MBB.end() || MBBI->getOpcode() != TII->getCatchReturnOpcode())
      continue;

    // FIXME: SEH CatchPads are not necessarily in the parent function:
    // they could be inside a finally block.
    const MachineBasicBlock *Successor = MBBI->getOperand(0).getMBB();
    const MachineBasicBlock *SuccessorColor = MBBI->getOperand(1).getMBB();
    CatchRetSuccessors.push_back(
        {Successor, IsSEH ? EntryBBNumber : SuccessorColor->getNumber()});
  }

  // We don't have anything to do if there aren't any EH pads.
  if (EHScopeBlocks.empty())
    return EHScopeMembership;

  // Identify all the basic blocks reachable from the function entry.
  collectEHScopeMembers(EHScopeMembership, EntryBBNumber, &MF.front());
  // All blocks not part of a scope are in the parent function.
  for (const MachineBasicBlock *MBB : UnreachableBlocks)
    collectEHScopeMembers(EHScopeMembership, EntryBBNumber, MBB);
  // Next, identify all the blocks inside the scopes.
  for (const MachineBasicBlock *MBB : EHScopeBlocks)
    collectEHScopeMembers(EHScopeMembership, MBB->getNumber(), MBB);
  // SEH CatchPads aren't really scopes, handle them separately.
  for (const MachineBasicBlock *MBB : SEHCatchPads)
    collectEHScopeMembers(EHScopeMembership, EntryBBNumber, MBB);
  // Finally, identify all the targets of a catchret.
  for (std::pair<const MachineBasicBlock *, int> CatchRetPair :
       CatchRetSuccessors)
    collectEHScopeMembers(EHScopeMembership, CatchRetPair.second,
                          CatchRetPair.first);

  // Add any remaining blocks in the function to the unreachable set, which
  // might not otherwise have been identified as unreachable (such as infinite
  // loops).
  for (const MachineBasicBlock &MBB : MF)
    if (!EHScopeMembership.count(&MBB))
      collectEHScopeMembers(EHScopeMembership, EntryBBNumber, &MBB);

  return EHScopeMembership;
}
