//===- DXILResourceAccess.cpp - Resource access via load/store ------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "DXILResourceAccess.h"
#include "DirectX.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/Analysis/DXILResource.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Analysis/VectorUtils.h"
#include "llvm/Frontend/HLSL/HLSLResource.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicsDirectX.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/ProfDataUtils.h"
#include "llvm/IR/User.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/DXILABI.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/KnownBits.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
#include <optional>

#define DEBUG_TYPE "dxil-resource-access"

using namespace llvm;

[[noreturn]] static void
diagnoseNonUniqueResourceAccess(Instruction *I,
                                ArrayRef<IntrinsicInst *> Handles) {
  LLVMContext &Context = I->getContext();
  std::string InstStr;
  raw_string_ostream InstOS(InstStr);
  I->print(InstOS);
  Context.diagnose(
      DiagnosticInfoGeneric("At resource access:" + Twine(InstStr), DS_Note));

  for (auto *Handle : Handles) {
    std::string HandleStr;
    raw_string_ostream HandleOS(HandleStr);
    Handle->print(HandleOS);
    Context.diagnose(DiagnosticInfoGeneric(
        "Uses resource handle:" + Twine(HandleStr), DS_Note));
  }
  report_fatal_error(
      "Resource access is not guaranteed to map to a unique global resource",
      /*gen_crash_diag=*/false);
}

static Value *traverseGEPOffsets(const DataLayout &DL, IRBuilder<> &Builder,
                                 Value *Ptr, uint64_t AccessSize) {
  Value *Offset = nullptr;

  while (Ptr) {
    if ([[maybe_unused]] auto *II = dyn_cast<IntrinsicInst>(Ptr)) {
      assert((II->getIntrinsicID() == Intrinsic::dx_resource_getpointer ||
              II->getIntrinsicID() == Intrinsic::dx_resource_getbasepointer) &&
             "Resource access through unexpected intrinsic");
      return Offset ? Offset : ConstantInt::get(Builder.getInt32Ty(), 0);
    }

    auto *GEP = dyn_cast<GetElementPtrInst>(Ptr);
    assert(GEP && "Resource access through unexpected instruction");

    unsigned NumIndices = GEP->getNumIndices();
    uint64_t IndexScale = DL.getTypeAllocSize(GEP->getSourceElementType());
    APInt ConstantOffset(DL.getIndexTypeSizeInBits(GEP->getType()), 0);
    Value *GEPOffset;
    if (GEP->accumulateConstantOffset(DL, ConstantOffset)) {
      // We have a constant offset (in bytes).
      GEPOffset =
          ConstantInt::get(DL.getIndexType(GEP->getType()), ConstantOffset);
      IndexScale = 1;
    } else if (NumIndices == 1) {
      // If we have a single index we're indexing into a top level array. This
      // generally only happens with cbuffers.
      GEPOffset = *GEP->idx_begin();
    } else if (NumIndices == 2) {
      // If we have two indices, this should be an access through a pointer.
      auto *IndexIt = GEP->idx_begin();
      assert(cast<ConstantInt>(IndexIt)->getZExtValue() == 0 &&
             "GEP is not indexing through pointer");
      GEPOffset = *(++IndexIt);
    } else
      llvm_unreachable("Unhandled GEP structure for resource access");

    uint64_t ElemSize = AccessSize;
    if (!(IndexScale % ElemSize)) {
      // If our scale is an exact multiple of the access size, adjust the
      // scaling to avoid an unnecessary division.
      IndexScale /= ElemSize;
      ElemSize = 1;
    }
    if (IndexScale != 1)
      GEPOffset = Builder.CreateMul(
          GEPOffset, ConstantInt::get(Builder.getInt32Ty(), IndexScale));
    if (ElemSize != 1)
      GEPOffset = Builder.CreateUDiv(
          GEPOffset, ConstantInt::get(Builder.getInt32Ty(), ElemSize));

    Offset = Offset ? Builder.CreateAdd(Offset, GEPOffset) : GEPOffset;
    Ptr = GEP->getPointerOperand();
  }

  llvm_unreachable("GEP of null pointer?");
}

static void createTypedBufferStore(IntrinsicInst *II, StoreInst *SI,
                                   dxil::ResourceTypeInfo &RTI) {
  const DataLayout &DL = SI->getDataLayout();
  IRBuilder<> Builder(SI);
  Type *ContainedType = RTI.getHandleTy()->getTypeParameter(0);
  Type *ScalarType = ContainedType->getScalarType();
  Type *LoadType = StructType::get(ContainedType, Builder.getInt1Ty());

  Value *V = SI->getValueOperand();
  if (V->getType() == ContainedType) {
    // V is already the right type.
    assert(SI->getPointerOperand() == II &&
           "Store of whole element has mismatched address to store to");
  } else if (V->getType() == ScalarType) {
    // We're storing a scalar, so we need to load the current value and only
    // replace the relevant part.
    auto *Load = Builder.CreateIntrinsic(
        LoadType, Intrinsic::dx_resource_load_typedbuffer,
        {II->getOperand(0), II->getOperand(1)});
    auto *Struct = Builder.CreateExtractValue(Load, {0});

    uint64_t AccessSize = DL.getTypeSizeInBits(ScalarType) / 8;
    Value *Offset =
        traverseGEPOffsets(DL, Builder, SI->getPointerOperand(), AccessSize);
    V = Builder.CreateInsertElement(Struct, V, Offset);
  } else {
    llvm_unreachable("Store to typed resource has invalid type");
  }

  auto *Inst = Builder.CreateIntrinsic(
      Builder.getVoidTy(), Intrinsic::dx_resource_store_typedbuffer,
      {II->getOperand(0), II->getOperand(1), V});
  SI->replaceAllUsesWith(Inst);
}

/// Build a zero-initialized offset operand matching the shape of the given
/// coordinate operand. Accesses through `operator[]` never have offsets.
static Value *getNullOffsetsFor(IRBuilder<> &Builder, Value *Coords) {
  Type *CoordTy = Coords->getType();
  Type *OffsetTy;
  if (auto *VecTy = dyn_cast<FixedVectorType>(CoordTy))
    OffsetTy =
        FixedVectorType::get(Builder.getInt32Ty(), VecTy->getNumElements());
  else
    OffsetTy = Builder.getInt32Ty();
  return Constant::getNullValue(OffsetTy);
}

static void createTextureStore(IntrinsicInst *II, StoreInst *SI,
                               dxil::ResourceTypeInfo &RTI) {
  const DataLayout &DL = SI->getDataLayout();
  IRBuilder<> Builder(SI);
  Type *ContainedType = RTI.getHandleTy()->getTypeParameter(0);
  Type *ScalarType = ContainedType->getScalarType();

  Value *Handle = II->getOperand(0);
  Value *Coords = II->getOperand(1);

  Value *V = SI->getValueOperand();
  if (V->getType() == ContainedType) {
    // V is already the right type.
    assert(SI->getPointerOperand() == II &&
           "Store of whole element has mismatched address to store to");
  } else if (V->getType() == ScalarType) {
    // We're storing a scalar, so we need to load the current value and only
    // replace the relevant part. For operator[] the mip level and the offsets
    // are always zero; DXILOpLowering drops the mip level for UAVs.
    Value *MipLevel = Builder.getInt32(0);
    Value *Offsets = getNullOffsetsFor(Builder, Coords);
    auto *Load = Builder.CreateIntrinsic(ContainedType,
                                         Intrinsic::dx_resource_load_level,
                                         {Handle, Coords, MipLevel, Offsets});

    uint64_t AccessSize = DL.getTypeSizeInBits(ScalarType) / 8;
    Value *Offset =
        traverseGEPOffsets(DL, Builder, SI->getPointerOperand(), AccessSize);
    V = Builder.CreateInsertElement(Load, V, Offset);
  } else {
    llvm_unreachable("Store to texture resource has invalid type");
  }

  auto *Inst = Builder.CreateIntrinsic(Builder.getVoidTy(),
                                       Intrinsic::dx_resource_store_texture,
                                       {Handle, Coords, V});
  SI->replaceAllUsesWith(Inst);
}

static void emitRawStore(IRBuilder<> &Builder, Value *Buffer, Value *Index,
                         Value *Offset, Value *V, dxil::ResourceTypeInfo &RTI) {
  // For raw buffer (ie, HLSL's ByteAddressBuffer), we need to fold the access
  // entirely into the index.
  if (!RTI.isStruct()) {
    auto *ConstantOffset = dyn_cast<ConstantInt>(Offset);
    if (!ConstantOffset || !ConstantOffset->isZero())
      Index = Builder.CreateAdd(Index, Offset);
    Offset = llvm::PoisonValue::get(Builder.getInt32Ty());
  }

  Builder.CreateIntrinsic(Builder.getVoidTy(),
                          Intrinsic::dx_resource_store_rawbuffer,
                          {Buffer, Index, Offset, V});
}

static void createRawStores(IntrinsicInst *II, StoreInst *SI,
                            dxil::ResourceTypeInfo &RTI) {
  const DataLayout &DL = SI->getDataLayout();
  IRBuilder<> Builder(SI);

  Value *V = SI->getValueOperand();
  assert(!V->getType()->isAggregateType() &&
         "Resource store should be scalar or vector type");

  Value *Index = II->getOperand(1);
  // The offset for the rawbuffer load and store ops is always in bytes.
  uint64_t AccessSize = 1;
  Value *Offset =
      traverseGEPOffsets(DL, Builder, SI->getPointerOperand(), AccessSize);

  auto *VT = dyn_cast<FixedVectorType>(V->getType());
  if (VT && VT->getNumElements() > 4) {
    // Split into stores of at most 4 elements.
    Type *EltTy = VT->getElementType();
    Value *Stride = ConstantInt::get(Builder.getInt32Ty(),
                                     4 * (DL.getTypeSizeInBits(EltTy) / 8));

    SmallVector<int, 4> Indices;
    for (unsigned int I = 0, N = VT->getNumElements(); I < N; I += 4) {
      if (I > 0)
        Offset = Builder.CreateAdd(Offset, Stride);

      for (unsigned int J = I, E = std::min(N, J + 4); J < E; ++J)
        Indices.push_back(J);
      Value *Part = Builder.CreateShuffleVector(V, Indices);
      emitRawStore(Builder, II->getOperand(0), Index, Offset, Part, RTI);

      Indices.clear();
    }
  } else
    emitRawStore(Builder, II->getOperand(0), Index, Offset, V, RTI);
}

static void createStoreIntrinsic(IntrinsicInst *II, StoreInst *SI,
                                 dxil::ResourceTypeInfo &RTI) {
  switch (RTI.getResourceKind()) {
  case dxil::ResourceKind::TypedBuffer:
    return createTypedBufferStore(II, SI, RTI);
  case dxil::ResourceKind::RawBuffer:
  case dxil::ResourceKind::StructuredBuffer:
    return createRawStores(II, SI, RTI);
  case dxil::ResourceKind::Texture1D:
  case dxil::ResourceKind::Texture2D:
  case dxil::ResourceKind::Texture3D:
  case dxil::ResourceKind::Texture1DArray:
  case dxil::ResourceKind::Texture2DArray:
    return createTextureStore(II, SI, RTI);
  case dxil::ResourceKind::Texture2DMS:
  case dxil::ResourceKind::Texture2DMSArray:
  case dxil::ResourceKind::TextureCube:
  case dxil::ResourceKind::TextureCubeArray:
  case dxil::ResourceKind::FeedbackTexture2D:
  case dxil::ResourceKind::FeedbackTexture2DArray:
    reportFatalUsageError(
        "DXIL Store not implemented for this texture resource kind");
    return;
  case dxil::ResourceKind::CBuffer:
  case dxil::ResourceKind::Sampler:
  case dxil::ResourceKind::TBuffer:
  case dxil::ResourceKind::RTAccelerationStructure:
  case dxil::ResourceKind::Invalid:
  case dxil::ResourceKind::NumEntries:
    llvm_unreachable("Invalid resource kind for store");
  }
  llvm_unreachable("Unhandled case in switch");
}

static std::optional<dxil::AtomicBinOpCode>
getAtomicBinOpCode(AtomicRMWInst::BinOp BinOp) {
  switch (BinOp) {
  case AtomicRMWInst::Add:
    return dxil::AtomicBinOpCode::Add;
  case AtomicRMWInst::And:
    return dxil::AtomicBinOpCode::And;
  case AtomicRMWInst::Or:
    return dxil::AtomicBinOpCode::Or;
  case AtomicRMWInst::Xor:
    return dxil::AtomicBinOpCode::Xor;
  case AtomicRMWInst::Min:
    return dxil::AtomicBinOpCode::IMin;
  case AtomicRMWInst::Max:
    return dxil::AtomicBinOpCode::IMax;
  case AtomicRMWInst::UMin:
    return dxil::AtomicBinOpCode::UMin;
  case AtomicRMWInst::UMax:
    return dxil::AtomicBinOpCode::UMax;
  case AtomicRMWInst::Xchg:
    return dxil::AtomicBinOpCode::Exchange;
  case AtomicRMWInst::Sub:
  case AtomicRMWInst::Nand:
  case AtomicRMWInst::FAdd:
  case AtomicRMWInst::FSub:
  case AtomicRMWInst::FMax:
  case AtomicRMWInst::FMin:
  case AtomicRMWInst::FMaximum:
  case AtomicRMWInst::FMinimum:
  case AtomicRMWInst::FMaximumNum:
  case AtomicRMWInst::FMinimumNum:
  case AtomicRMWInst::UIncWrap:
  case AtomicRMWInst::UDecWrap:
  case AtomicRMWInst::USubCond:
  case AtomicRMWInst::USubSat:
  case AtomicRMWInst::BAD_BINOP:
    return std::nullopt;
  }
  llvm_unreachable("Unhandled atomicrmw operation");
}

// Compute the (coord0, coord1) pair for a buffer resource atomic operation.
// Non-struct buffers (RawBuffer or TypedBuffer) fold the byte offset into the
// index and leave coord1 poison. Only StructuredBuffer atomics use both a
// struct index and a byte offset.
static std::pair<Value *, Value *>
getAtomicResourceCoords(IntrinsicInst *II, Value *PointerOperand,
                        dxil::ResourceTypeInfo &RTI, IRBuilder<> &Builder,
                        const DataLayout &DL) {
  Value *Index = II->getOperand(1);

  // The offset for the rawbuffer load/store/atomic ops is always in bytes.
  uint64_t AccessSize = 1;
  Value *Offset = traverseGEPOffsets(DL, Builder, PointerOperand, AccessSize);

  if (!RTI.isStruct()) {
    auto *ConstantOffset = dyn_cast<ConstantInt>(Offset);
    if (!ConstantOffset || !ConstantOffset->isZero())
      Index = Builder.CreateAdd(Index, Offset);
    Offset = llvm::PoisonValue::get(Builder.getInt32Ty());
  }

  return {Index, Offset};
}

// The coordinates of a texture access are a scalar or a vector with one element
// per texture dimension, including the array slice if there is one. These map
// directly onto the coordinate operands of the atomic ops.
static SmallVector<Value *, 3> getTextureAtomicCoords(IntrinsicInst *II,
                                                      IRBuilder<> &Builder) {
  Value *Coords = II->getOperand(1);
  SmallVector<Value *, 3> CoordArgs;
  if (auto *VecTy = dyn_cast<FixedVectorType>(Coords->getType())) {
    assert(VecTy->getNumElements() <= 3 && "Too many texture coordinates");
    for (unsigned I = 0, E = VecTy->getNumElements(); I != E; ++I)
      CoordArgs.push_back(Builder.CreateExtractElement(Coords, I));
  } else {
    CoordArgs.push_back(Coords);
  }
  return CoordArgs;
}

static void emitAtomicBinOp(IRBuilder<> &Builder, AtomicRMWInst *AI,
                            Value *Handle, ArrayRef<Value *> Coords) {
  assert(!Coords.empty() && Coords.size() <= 3 &&
         "Atomic operations take between one and three coordinates");

  std::optional<dxil::AtomicBinOpCode> BinOpCode =
      getAtomicBinOpCode(AI->getOperation());
  if (!BinOpCode) {
    reportFatalUsageError("DXIL resource atomicrmw operation not implemented");
    return;
  }

  // DXIL has no floating-point atomic op. A float exchange only moves the bit
  // pattern, so cast the value to an integer of the same width, exchange, and
  // cast the result back. This matches what DXC emits.
  Value *Val = AI->getValOperand();
  Type *ValTy = Val->getType();
  Type *OpTy = ValTy;
  if (ValTy->isFloatingPointTy()) {
    OpTy = Builder.getIntNTy(ValTy->getPrimitiveSizeInBits());
    Val = Builder.CreateBitCast(Val, OpTy);
  }

  SmallVector<Value *, 6> Args{
      Handle, Builder.getInt32(static_cast<uint32_t>(*BinOpCode))};
  append_range(Args, Coords);
  Args.append(3 - Coords.size(), PoisonValue::get(Builder.getInt32Ty()));
  Args.push_back(Val);

  // Emit the target-independent intrinsic; DXILOpLowering lowers it to the
  // DXIL `AtomicBinOp` op and handles the target-ext-typed handle cast via
  // its `createTmpHandleCast` bookkeeping.
  Value *Result =
      Builder.CreateIntrinsic(OpTy, Intrinsic::dx_resource_atomic_binop, Args);

  if (OpTy != ValTy)
    Result = Builder.CreateBitCast(Result, ValTy);

  AI->replaceAllUsesWith(Result);
}

static void createBufferAtomicBinOp(IntrinsicInst *II, AtomicRMWInst *AI,
                                    dxil::ResourceTypeInfo &RTI) {
  const DataLayout &DL = AI->getDataLayout();
  IRBuilder<> Builder(AI);
  auto [Index, Offset] =
      getAtomicResourceCoords(II, AI->getPointerOperand(), RTI, Builder, DL);

  emitAtomicBinOp(Builder, AI, II->getOperand(0), {Index, Offset});
}

static void createTextureAtomicBinOp(IntrinsicInst *II, AtomicRMWInst *AI,
                                     dxil::ResourceTypeInfo &RTI) {
  // A texture atomic operates on a whole texel, so a multi-component texel has
  // no single addressable component. A scalar float texel is allowed, because
  // emitAtomicBinOp exchanges its bit pattern as an integer.
  Type *ContainedType = RTI.getHandleTy()->getTypeParameter(0);
  if (!ContainedType->isIntegerTy() && !ContainedType->isFloatingPointTy()) {
    reportFatalUsageError("DXIL atomicrmw requires a texture resource with a "
                          "scalar element type");
    return;
  }

  IRBuilder<> Builder(AI);

  emitAtomicBinOp(Builder, AI, II->getOperand(0),
                  getTextureAtomicCoords(II, Builder));
}

static void emitAtomicCompareExchange(IRBuilder<> &Builder,
                                      AtomicCmpXchgInst *AI, Value *Handle,
                                      ArrayRef<Value *> Coords) {
  assert(!Coords.empty() && Coords.size() <= 3 &&
         "Atomic operations take between one and three coordinates");

  Value *Compare = AI->getCompareOperand();
  Value *NewValue = AI->getNewValOperand();

  SmallVector<Value *, 6> Args{Handle};
  append_range(Args, Coords);
  Args.append(3 - Coords.size(), PoisonValue::get(Builder.getInt32Ty()));
  Args.push_back(Compare);
  Args.push_back(NewValue);

  Value *Original = Builder.CreateIntrinsic(
      NewValue->getType(), Intrinsic::dx_resource_atomic_compare_exchange,
      Args);

  // `cmpxchg` yields a { original, success } pair, but the DXIL op returns
  // only the original value. DXIL has no way to express the success flag, and
  // no HLSL builtin reads it, so replace the users of the pair directly
  // instead of building it again. No pass after this one removes dead code.
  SmallVector<ExtractValueInst *> Extracts;
  for (User *U : AI->users()) {
    auto *EV = dyn_cast<ExtractValueInst>(U);
    if (!EV || EV->getIndices()[0] != 0)
      reportFatalUsageError("DXIL cmpxchg provides only the original value");
    Extracts.push_back(EV);
  }

  for (ExtractValueInst *EV : Extracts) {
    EV->replaceAllUsesWith(Original);
    EV->eraseFromParent();
  }
}

static void createBufferAtomicCompareExchange(IntrinsicInst *II,
                                              AtomicCmpXchgInst *AI,
                                              dxil::ResourceTypeInfo &RTI) {
  const DataLayout &DL = AI->getDataLayout();
  IRBuilder<> Builder(AI);
  auto [Index, Offset] =
      getAtomicResourceCoords(II, AI->getPointerOperand(), RTI, Builder, DL);

  emitAtomicCompareExchange(Builder, AI, II->getOperand(0), {Index, Offset});
}

// `cmpxchg` operands are always integers, so unlike atomicrmw there is no
// float element type to convert here. The element type must be scalar.
static void createTextureAtomicCompareExchange(IntrinsicInst *II,
                                               AtomicCmpXchgInst *AI,
                                               dxil::ResourceTypeInfo &RTI) {
  Type *ContainedType = RTI.getHandleTy()->getTypeParameter(0);
  if (!ContainedType->isIntegerTy() && !ContainedType->isFloatingPointTy()) {
    reportFatalUsageError("DXIL cmpxchg requires a texture resource with a "
                          "scalar element type");
    return;
  }

  IRBuilder<> Builder(AI);

  emitAtomicCompareExchange(Builder, AI, II->getOperand(0),
                            getTextureAtomicCoords(II, Builder));
}

static void createAtomicBinOpIntrinsic(IntrinsicInst *II, AtomicRMWInst *AI,
                                       dxil::ResourceTypeInfo &RTI) {
  switch (RTI.getResourceKind()) {
  case dxil::ResourceKind::TypedBuffer:
  case dxil::ResourceKind::RawBuffer:
  case dxil::ResourceKind::StructuredBuffer:
    return createBufferAtomicBinOp(II, AI, RTI);
  case dxil::ResourceKind::Texture1D:
  case dxil::ResourceKind::Texture2D:
  case dxil::ResourceKind::Texture3D:
  case dxil::ResourceKind::Texture1DArray:
  case dxil::ResourceKind::Texture2DArray:
    return createTextureAtomicBinOp(II, AI, RTI);
  case dxil::ResourceKind::Texture2DMS:
  case dxil::ResourceKind::Texture2DMSArray:
  case dxil::ResourceKind::TextureCube:
  case dxil::ResourceKind::TextureCubeArray:
  case dxil::ResourceKind::FeedbackTexture2D:
  case dxil::ResourceKind::FeedbackTexture2DArray:
    reportFatalUsageError(
        "DXIL atomicrmw not implemented for this texture resource kind");
    return;
  case dxil::ResourceKind::CBuffer:
  case dxil::ResourceKind::Sampler:
  case dxil::ResourceKind::TBuffer:
    reportFatalUsageError(
        "DXIL atomicrmw not implemented for this resource type");
    return;
  case dxil::ResourceKind::RTAccelerationStructure:
  case dxil::ResourceKind::Invalid:
  case dxil::ResourceKind::NumEntries:
    llvm_unreachable("Invalid resource kind for atomicrmw");
  }
  llvm_unreachable("Unhandled case in switch");
}

static void createAtomicCompareExchangeIntrinsic(IntrinsicInst *II,
                                                 AtomicCmpXchgInst *AI,
                                                 dxil::ResourceTypeInfo &RTI) {
  switch (RTI.getResourceKind()) {
  case dxil::ResourceKind::TypedBuffer:
  case dxil::ResourceKind::RawBuffer:
  case dxil::ResourceKind::StructuredBuffer:
    return createBufferAtomicCompareExchange(II, AI, RTI);
  case dxil::ResourceKind::Texture1D:
  case dxil::ResourceKind::Texture2D:
  case dxil::ResourceKind::Texture3D:
  case dxil::ResourceKind::Texture1DArray:
  case dxil::ResourceKind::Texture2DArray:
    return createTextureAtomicCompareExchange(II, AI, RTI);
  case dxil::ResourceKind::Texture2DMS:
  case dxil::ResourceKind::Texture2DMSArray:
  case dxil::ResourceKind::TextureCube:
  case dxil::ResourceKind::TextureCubeArray:
  case dxil::ResourceKind::FeedbackTexture2D:
  case dxil::ResourceKind::FeedbackTexture2DArray:
    reportFatalUsageError(
        "DXIL cmpxchg not implemented for this texture resource kind");
    return;
  case dxil::ResourceKind::CBuffer:
  case dxil::ResourceKind::Sampler:
  case dxil::ResourceKind::TBuffer:
    reportFatalUsageError(
        "DXIL cmpxchg not implemented for this resource type");
    return;
  case dxil::ResourceKind::RTAccelerationStructure:
  case dxil::ResourceKind::Invalid:
  case dxil::ResourceKind::NumEntries:
    llvm_unreachable("Invalid resource kind for cmpxchg");
  }
  llvm_unreachable("Unhandled case in switch");
}

static void createTypedBufferLoad(IntrinsicInst *II, LoadInst *LI,
                                  dxil::ResourceTypeInfo &RTI) {
  const DataLayout &DL = LI->getDataLayout();
  IRBuilder<> Builder(LI);
  Type *ContainedType = RTI.getHandleTy()->getTypeParameter(0);
  Type *LoadType = StructType::get(ContainedType, Builder.getInt1Ty());

  Value *V =
      Builder.CreateIntrinsic(LoadType, Intrinsic::dx_resource_load_typedbuffer,
                              {II->getOperand(0), II->getOperand(1)});
  V = Builder.CreateExtractValue(V, {0});

  Type *ScalarType = ContainedType->getScalarType();
  uint64_t AccessSize = DL.getTypeSizeInBits(ScalarType) / 8;
  Value *Offset =
      traverseGEPOffsets(DL, Builder, LI->getPointerOperand(), AccessSize);
  auto *ConstantOffset = dyn_cast<ConstantInt>(Offset);
  if (!ConstantOffset || !ConstantOffset->isZero())
    V = Builder.CreateExtractElement(V, Offset);

  // If we loaded a <1 x ...> instead of a scalar (presumably to feed a
  // shufflevector), then make sure we're maintaining the resulting type.
  if (auto *VT = dyn_cast<FixedVectorType>(LI->getType()))
    if (VT->getNumElements() == 1 && !isa<FixedVectorType>(V->getType()))
      V = Builder.CreateInsertElement(PoisonValue::get(VT), V,
                                      Builder.getInt32(0));

  LI->replaceAllUsesWith(V);
}

static void createTextureLoad(IntrinsicInst *II, LoadInst *LI,
                              dxil::ResourceTypeInfo &RTI) {
  const DataLayout &DL = LI->getDataLayout();
  IRBuilder<> Builder(LI);
  Type *ContainedType = RTI.getHandleTy()->getTypeParameter(0);

  Value *Handle = II->getOperand(0);
  Value *Coords = II->getOperand(1);

  // For operator[], mip level is 0.
  Value *MipLevel = Builder.getInt32(0);

  // For operator[], offsets are zero.
  Value *Offsets = getNullOffsetsFor(Builder, Coords);

  Value *V =
      Builder.CreateIntrinsic(ContainedType, Intrinsic::dx_resource_load_level,
                              {Handle, Coords, MipLevel, Offsets});

  Type *ScalarType = ContainedType->getScalarType();
  uint64_t AccessSize = DL.getTypeSizeInBits(ScalarType) / 8;
  Value *Offset =
      traverseGEPOffsets(DL, Builder, LI->getPointerOperand(), AccessSize);
  auto *ConstantOffset = dyn_cast<ConstantInt>(Offset);
  if (!ConstantOffset || !ConstantOffset->isZero())
    V = Builder.CreateExtractElement(V, Offset);

  // If we loaded a <1 x ...> instead of a scalar (presumably to feed a
  // shufflevector), then make sure we're maintaining the resulting type.
  if (auto *VT = dyn_cast<FixedVectorType>(LI->getType()))
    if (VT->getNumElements() == 1 && !isa<FixedVectorType>(V->getType()))
      V = Builder.CreateInsertElement(PoisonValue::get(VT), V,
                                      Builder.getInt32(0));

  LI->replaceAllUsesWith(V);
}

static Value *emitRawLoad(IRBuilder<> &Builder, Type *Ty, Value *Buffer,
                          Value *Index, Value *Offset,
                          dxil::ResourceTypeInfo &RTI) {
  // For raw buffer (ie, HLSL's ByteAddressBuffer), we need to fold the access
  // entirely into the index.
  if (!RTI.isStruct()) {
    auto *ConstantOffset = dyn_cast<ConstantInt>(Offset);
    if (!ConstantOffset || !ConstantOffset->isZero())
      Index = Builder.CreateAdd(Index, Offset);
    Offset = llvm::PoisonValue::get(Builder.getInt32Ty());
  }

  // The load intrinsic includes the bit for CheckAccessFullyMapped, so we need
  // to add that to the return type.
  Type *TypeWithCheck = StructType::get(Ty, Builder.getInt1Ty());
  Value *V = Builder.CreateIntrinsic(TypeWithCheck,
                                     Intrinsic::dx_resource_load_rawbuffer,
                                     {Buffer, Index, Offset});
  return Builder.CreateExtractValue(V, {0});
}

static void createRawLoads(IntrinsicInst *II, LoadInst *LI,
                           dxil::ResourceTypeInfo &RTI) {
  const DataLayout &DL = LI->getDataLayout();
  IRBuilder<> Builder(LI);

  Value *Index = II->getOperand(1);
  // The offset for the rawbuffer load and store ops is always in bytes.
  uint64_t AccessSize = 1;
  Value *Offset =
      traverseGEPOffsets(DL, Builder, LI->getPointerOperand(), AccessSize);

  // TODO: We could make this handle aggregates by walking the structure and
  // handling each field individually, but we don't ever generate code that
  // would hit that so it seems superfluous.
  assert(!LI->getType()->isAggregateType() &&
         "Resource load should be scalar or vector type");

  Value *V;
  if (auto *VT = dyn_cast<FixedVectorType>(LI->getType())) {
    // Split into loads of at most 4 elements.
    Type *EltTy = VT->getElementType();
    Value *Stride = ConstantInt::get(Builder.getInt32Ty(),
                                     4 * (DL.getTypeSizeInBits(EltTy) / 8));

    SmallVector<Value *> Parts;
    for (unsigned int I = 0, N = VT->getNumElements(); I < N; I += 4) {
      Type *Ty = FixedVectorType::get(EltTy, N - I < 4 ? N - I : 4);
      if (I > 0)
        Offset = Builder.CreateAdd(Offset, Stride);
      Parts.push_back(
          emitRawLoad(Builder, Ty, II->getOperand(0), Index, Offset, RTI));
    }

    V = Parts.size() > 1 ? concatenateVectors(Builder, Parts) : Parts[0];
  } else
    V = emitRawLoad(Builder, LI->getType(), II->getOperand(0), Index, Offset,
                    RTI);

  LI->replaceAllUsesWith(V);
}

namespace {
/// Helper for building a `load.cbufferrow` intrinsic given a simple type.
struct CBufferRowIntrin {
  Intrinsic::ID IID;
  Type *RetTy;
  unsigned int EltSize;
  unsigned int NumElts;

  CBufferRowIntrin(const DataLayout &DL, Type *Ty) {
    assert(Ty == Ty->getScalarType() && "Expected scalar type");

    switch (DL.getTypeSizeInBits(Ty)) {
    case 16:
      IID = Intrinsic::dx_resource_load_cbufferrow_8;
      RetTy = StructType::get(Ty, Ty, Ty, Ty, Ty, Ty, Ty, Ty);
      EltSize = 2;
      NumElts = 8;
      break;
    case 32:
      IID = Intrinsic::dx_resource_load_cbufferrow_4;
      RetTy = StructType::get(Ty, Ty, Ty, Ty);
      EltSize = 4;
      NumElts = 4;
      break;
    case 64:
      IID = Intrinsic::dx_resource_load_cbufferrow_2;
      RetTy = StructType::get(Ty, Ty);
      EltSize = 8;
      NumElts = 2;
      break;
    default:
      llvm_unreachable("Only 16, 32, and 64 bit types supported");
    }
  }
};
} // namespace

static Value *loadCBufferRowIntoWindow(IRBuilder<> &Builder,
                                       const CBufferRowIntrin &Intrin,
                                       Value *Handle, Value *FirstRow,
                                       Value *Window, unsigned RowNumber,
                                       StringRef Name) {
  Value *RowIndex =
      RowNumber == 0 ? FirstRow
                     : Builder.CreateAdd(FirstRow, Builder.getInt32(RowNumber));
  Value *RowLoad = Builder.CreateIntrinsic(
      Intrin.RetTy, Intrin.IID, {Handle, RowIndex}, nullptr, Name + ".load");
  for (unsigned J = 0; J != Intrin.NumElts; ++J) {
    Value *Element = Builder.CreateExtractValue(RowLoad, {J});
    Window = Builder.CreateInsertElement(
        Window, Element, Builder.getInt32(RowNumber * Intrin.NumElts + J));
  }
  return Window;
}

static Value *createDynamicCBufferLoad(IntrinsicInst *II, LoadInst *LI,
                                       const CBufferRowIntrin &Intrin,
                                       Value *BaseRow, Value *ByteOffset,
                                       const KnownBits &WithinRow) {
  IRBuilder<> Builder(LI);
  Type *Ty = LI->getType();
  auto *VT = dyn_cast<FixedVectorType>(Ty);
  unsigned NumElements = VT ? VT->getNumElements() : 1;
  StringRef Name = LI->getName();
  Value *Handle = II->getOperand(0);
  Value *RowSize = Builder.getInt32(hlsl::CBufferRowSizeInBytes);
  Value *FirstRow =
      Builder.CreateAdd(BaseRow, Builder.CreateUDiv(ByteOffset, RowSize));
  Value *Component = Builder.CreateUDiv(Builder.CreateURem(ByteOffset, RowSize),
                                        Builder.getInt32(Intrin.EltSize));
  unsigned MinComponent =
      WithinRow.getMinValue().getZExtValue() / Intrin.EltSize;
  unsigned MaxComponent =
      WithinRow.getMaxValue().getZExtValue() / Intrin.EltSize;
  unsigned MinRows = 1 + (MinComponent + NumElements - 1) / Intrin.NumElts;
  unsigned MaxRows = 1 + (MaxComponent + NumElements - 1) / Intrin.NumElts;
  auto *WindowTy =
      FixedVectorType::get(Ty->getScalarType(), MaxRows * Intrin.NumElts);
  Value *Window = PoisonValue::get(WindowTy);
  for (unsigned I = 0; I != MinRows; ++I)
    Window = loadCBufferRowIntoWindow(Builder, Intrin, Handle, FirstRow, Window,
                                      I, Name);

  // The unknown starting component can require at most one extra row.
  // Load it only when needed, rather than accessing beyond the load.
  if (MaxRows != MinRows) {
    BasicBlock *Head = LI->getParent();
    Value *LastComponent =
        Builder.CreateAdd(Component, Builder.getInt32(NumElements - 1));
    Value *CrossesRow = Builder.CreateICmpUGE(
        LastComponent, Builder.getInt32(MinRows * Intrin.NumElts));
    Instruction *ThenTerm = SplitBlockAndInsertIfThen(CrossesRow, LI, false);
    setExplicitlyUnknownBranchWeightsIfProfiled(*Head->getTerminator(),
                                                DEBUG_TYPE);
    Builder.SetInsertPoint(ThenTerm);
    Value *NextWindow = loadCBufferRowIntoWindow(
        Builder, Intrin, Handle, FirstRow, Window, MinRows, Name);
    Builder.SetInsertPoint(LI);
    auto *Rows = Builder.CreatePHI(WindowTy, 2, Name + ".rows");
    Rows->addIncoming(Window, Head);
    Rows->addIncoming(NextWindow, ThenTerm->getParent());
    Window = Rows;
  }

  Value *Result = PoisonValue::get(Ty);
  for (unsigned I = 0; I != NumElements; ++I) {
    Value *Index =
        I == 0 ? Component : Builder.CreateAdd(Component, Builder.getInt32(I));
    Value *Element =
        Builder.CreateExtractElement(Window, Index, Name + ".extract");
    Result =
        VT ? Builder.CreateInsertElement(Result, Element, Builder.getInt32(I))
           : Element;
  }
  return Result;
}

static KnownBits computeCBufferOffsetKnownBits(Value *Offset,
                                               const DataLayout &DL,
                                               const Instruction *CxtI) {
  KnownBits Known = computeKnownBits(Offset, DL, nullptr, CxtI);
  auto *Phi = dyn_cast<PHINode>(Offset);
  if (!Phi || Phi->getNumIncomingValues() == 0)
    return Known;

  // PHI queries limit recursion into each input, which can hide row alignment.
  KnownBits IncomingKnown(Known.getBitWidth());
  IncomingKnown.setAllConflict();
  for (unsigned I = 0; I != Phi->getNumIncomingValues(); ++I)
    IncomingKnown = IncomingKnown.intersectWith(
        computeKnownBits(Phi->getIncomingValue(I), DL, nullptr,
                         Phi->getIncomingBlock(I)->getTerminator()));
  return Known.unionWith(IncomingKnown);
}

static void createCBufferLoad(IntrinsicInst *II, LoadInst *LI,
                              dxil::ResourceTypeInfo &RTI) {
  const DataLayout &DL = LI->getDataLayout();

  Type *Ty = LI->getType();
  assert(!isa<StructType>(Ty) && "Structs not handled yet");
  CBufferRowIntrin Intrin(DL, Ty->getScalarType());

  StringRef Name = LI->getName();
  Value *Handle = II->getOperand(0);

  IRBuilder<> Builder(LI);

  ConstantInt *GlobalOffset =
      II->getIntrinsicID() == Intrinsic::dx_resource_getbasepointer
          ? ConstantInt::get(Builder.getInt32Ty(), 0)
          : dyn_cast<ConstantInt>(II->getOperand(1));
  assert(GlobalOffset && "CBuffer getpointer index must be constant");

  uint64_t GlobalOffsetVal = GlobalOffset->getZExtValue();
  Value *CurrentRow = ConstantInt::get(
      Builder.getInt32Ty(), GlobalOffsetVal / hlsl::CBufferRowSizeInBytes);
  unsigned int CurrentIndex =
      (GlobalOffsetVal % hlsl::CBufferRowSizeInBytes) / Intrin.EltSize;

  // Every object in a cbuffer either fits in a row or is aligned to a row. This
  // means that only the very last pointer access can point into a row.
  auto *LastGEP = dyn_cast<GEPOperator>(LI->getPointerOperand());
  if (!LastGEP) {
    // If we don't have a GEP at all we're just accessing the resource through
    // the result of getpointer directly.
    assert(LI->getPointerOperand() == II &&
           "Unexpected indirect access to resource without GEP");
  } else {
    Value *GEPOffset = traverseGEPOffsets(
        DL, Builder, LastGEP->getPointerOperand(), hlsl::CBufferRowSizeInBytes);
    CurrentRow = Builder.CreateAdd(GEPOffset, CurrentRow);

    APInt ConstantOffset(DL.getIndexTypeSizeInBits(LastGEP->getType()), 0);
    if (LastGEP->accumulateConstantOffset(DL, ConstantOffset)) {
      APInt Remainder(DL.getIndexTypeSizeInBits(LastGEP->getType()),
                      hlsl::CBufferRowSizeInBytes);
      APInt::udivrem(ConstantOffset, Remainder, ConstantOffset, Remainder);
      CurrentRow = Builder.CreateAdd(
          CurrentRow, ConstantInt::get(Builder.getInt32Ty(), ConstantOffset));
      CurrentIndex += Remainder.udiv(Intrin.EltSize).getZExtValue();
    } else {
      assert(LastGEP->getNumIndices() == 1 &&
             "Last GEP of cbuffer access is not array or struct access");
      // Aggregate strides are row-aligned, but merged byte offsets can select
      // different components within a row.
      Value *RowIndex = Builder.CreateSExtOrTrunc(*LastGEP->idx_begin(),
                                                  Builder.getInt32Ty());
      uint64_t IndexScale =
          DL.getTypeAllocSize(LastGEP->getSourceElementType());
      if (IndexScale < hlsl::CBufferRowSizeInBytes) {
        assert(hlsl::CBufferRowSizeInBytes % IndexScale == 0 &&
               "CBuffer GEP index is not row aligned");
        Value *ByteOffset =
            IndexScale == 1
                ? RowIndex
                : Builder.CreateMul(RowIndex, Builder.getInt32(IndexScale));
        uint64_t BaseWithinRow = GlobalOffsetVal % hlsl::CBufferRowSizeInBytes;
        if (BaseWithinRow != 0)
          ByteOffset =
              Builder.CreateAdd(ByteOffset, Builder.getInt32(BaseWithinRow));
        Value *RowSize = Builder.getInt32(hlsl::CBufferRowSizeInBytes);
        KnownBits WithinRow =
            computeCBufferOffsetKnownBits(ByteOffset, DL, LI) &
            KnownBits::makeConstant(APInt(32, hlsl::CBufferRowSizeInBytes - 1));
        if (!WithinRow.isConstant()) {
          LI->replaceAllUsesWith(createDynamicCBufferLoad(
              II, LI, Intrin, CurrentRow, ByteOffset, WithinRow));
          return;
        }
        RowIndex = Builder.CreateUDiv(ByteOffset, RowSize, "",
                                      WithinRow.getConstant().isZero());
        CurrentIndex = WithinRow.getConstant().getZExtValue() / Intrin.EltSize;
      } else if (IndexScale > hlsl::CBufferRowSizeInBytes) {
        assert(IndexScale % hlsl::CBufferRowSizeInBytes == 0 &&
               "CBuffer GEP index is not row aligned");
        RowIndex = Builder.CreateMul(
            RowIndex,
            ConstantInt::get(Builder.getInt32Ty(),
                             IndexScale / hlsl::CBufferRowSizeInBytes));
      }
      if (auto *BaseRow = dyn_cast<ConstantInt>(CurrentRow);
          BaseRow && BaseRow->isZero())
        CurrentRow = RowIndex;
      else
        CurrentRow = Builder.CreateAdd(CurrentRow, RowIndex);
    }
  }

  auto *CBufLoad = Builder.CreateIntrinsic(
      Intrin.RetTy, Intrin.IID, {Handle, CurrentRow}, nullptr, Name + ".load");
  auto *Elt =
      Builder.CreateExtractValue(CBufLoad, {CurrentIndex++}, Name + ".extract");

  // At this point we've loaded the first scalar of our result, but our original
  // type may have been a vector.
  unsigned int Remaining =
      ((DL.getTypeSizeInBits(Ty) / 8) / Intrin.EltSize) - 1;
  if (Remaining == 0) {
    // We only have a single element, so we're done.
    Value *Result = Elt;

    // However, if we loaded a <1 x T>, then we need to adjust the type.
    if (auto *VT = dyn_cast<FixedVectorType>(Ty)) {
      assert(VT->getNumElements() == 1 && "Can't have multiple elements here");
      Result = Builder.CreateInsertElement(PoisonValue::get(VT), Result,
                                           Builder.getInt32(0), Name);
    }
    LI->replaceAllUsesWith(Result);
    return;
  }

  // Walk each element and extract it, wrapping to new rows as needed.
  SmallVector<Value *> Extracts{Elt};
  while (Remaining--) {
    CurrentIndex %= Intrin.NumElts;

    if (CurrentIndex == 0) {
      CurrentRow = Builder.CreateAdd(CurrentRow,
                                     ConstantInt::get(Builder.getInt32Ty(), 1));
      CBufLoad = Builder.CreateIntrinsic(Intrin.RetTy, Intrin.IID,
                                         {Handle, CurrentRow}, nullptr,
                                         Name + ".load");
    }

    Extracts.push_back(Builder.CreateExtractValue(CBufLoad, {CurrentIndex++},
                                                  Name + ".extract"));
  }

  // Finally, we build up the original loaded value.
  Value *Result = PoisonValue::get(Ty);
  for (int I = 0, E = Extracts.size(); I < E; ++I)
    Result = Builder.CreateInsertElement(
        Result, Extracts[I], Builder.getInt32(I), Name + formatv(".upto{}", I));
  LI->replaceAllUsesWith(Result);
}

static void createLoadIntrinsic(IntrinsicInst *II, LoadInst *LI,
                                dxil::ResourceTypeInfo &RTI) {
  switch (RTI.getResourceKind()) {
  case dxil::ResourceKind::TypedBuffer:
    return createTypedBufferLoad(II, LI, RTI);
  case dxil::ResourceKind::RawBuffer:
  case dxil::ResourceKind::StructuredBuffer:
    return createRawLoads(II, LI, RTI);
  case dxil::ResourceKind::CBuffer:
    return createCBufferLoad(II, LI, RTI);
  case dxil::ResourceKind::Texture1D:
  case dxil::ResourceKind::Texture2D:
  case dxil::ResourceKind::Texture2DMS:
  case dxil::ResourceKind::Texture3D:
  case dxil::ResourceKind::TextureCube:
  case dxil::ResourceKind::Texture1DArray:
  case dxil::ResourceKind::Texture2DArray:
  case dxil::ResourceKind::Texture2DMSArray:
  case dxil::ResourceKind::TextureCubeArray:
    return createTextureLoad(II, LI, RTI);
  case dxil::ResourceKind::FeedbackTexture2D:
  case dxil::ResourceKind::FeedbackTexture2DArray:
  case dxil::ResourceKind::TBuffer:
    reportFatalUsageError("Load not yet implemented for resource type");
    return;
  case dxil::ResourceKind::Sampler:
  case dxil::ResourceKind::RTAccelerationStructure:
  case dxil::ResourceKind::Invalid:
  case dxil::ResourceKind::NumEntries:
    llvm_unreachable("Invalid resource kind for load");
  }
  llvm_unreachable("Unhandled case in switch");
}

static Instruction *getHandleOperand(Instruction *AI) {
  if (auto *LI = dyn_cast<LoadInst>(AI))
    return dyn_cast<Instruction>(LI->getPointerOperand());
  if (auto *SI = dyn_cast<StoreInst>(AI))
    return dyn_cast<Instruction>(SI->getPointerOperand());
  if (auto *RMWI = dyn_cast<AtomicRMWInst>(AI))
    return dyn_cast<Instruction>(RMWI->getPointerOperand());
  if (auto *CXI = dyn_cast<AtomicCmpXchgInst>(AI))
    return dyn_cast<Instruction>(CXI->getPointerOperand());
  if (auto *II = dyn_cast<IntrinsicInst>(AI))
    if (II->getIntrinsicID() == Intrinsic::dx_resource_updatecounter)
      return dyn_cast<Instruction>(II->getArgOperand(0));

  return nullptr;
}

static Instruction *getHandleRoot(Instruction *I) {
  while (auto *GEP = dyn_cast<GetElementPtrInst>(I)) {
    auto *PointerI = dyn_cast<Instruction>(GEP->getPointerOperand());
    if (!PointerI)
      break;
    I = PointerI;
  }
  return I;
}

static const std::array<Intrinsic::ID, 2> HandleIntrins = {
    Intrinsic::dx_resource_handlefrombinding,
    Intrinsic::dx_resource_handlefromimplicitbinding,
};

static SmallVector<IntrinsicInst *> collectUsedHandles(Value *Ptr) {
  SmallVector<Value *> Worklist = {Ptr};
  SmallVector<IntrinsicInst *> Handles;
  SmallPtrSet<Value *, 4> VisitedPhis;

  while (!Worklist.empty()) {
    Value *X = Worklist.pop_back_val();

    if (!X->getType()->isPointerTy() && !X->getType()->isTargetExtTy())
      return {}; // Early exit on store/load into non-resource

    if (auto *Phi = dyn_cast<PHINode>(X)) {
      if (VisitedPhis.contains(X))
        continue;
      for (Use &V : Phi->incoming_values())
        Worklist.push_back(V.get());
      VisitedPhis.insert(Phi);
    } else if (auto *Select = dyn_cast<SelectInst>(X)) {
      Worklist.push_back(Select->getTrueValue());
      Worklist.push_back(Select->getFalseValue());
    } else if (auto *GEP = dyn_cast<GetElementPtrInst>(X)) {
      Worklist.push_back(GEP->getPointerOperand());
    } else if (auto *II = dyn_cast<IntrinsicInst>(X)) {
      Intrinsic::ID IID = II->getIntrinsicID();

      if (IID == Intrinsic::dx_resource_getpointer ||
          IID == Intrinsic::dx_resource_getbasepointer)
        Worklist.push_back(II->getArgOperand(/*Handle=*/0));

      if (llvm::is_contained(HandleIntrins, IID))
        Handles.push_back(II);
    }
  }

  return Handles;
}

static hlsl::Binding getHandleIntrinsicBinding(IntrinsicInst *Handle,
                                               DXILResourceTypeMap &DRTM) {
  assert(llvm::is_contained(HandleIntrins, Handle->getIntrinsicID()) &&
         "Only expects a Handle as determined from collectUsedHandles.");

  auto *HandleTy = cast<TargetExtType>(Handle->getType());
  dxil::ResourceClass Class = DRTM[HandleTy].getResourceClass();
  uint32_t Space = cast<ConstantInt>(Handle->getArgOperand(0))->getZExtValue();
  uint32_t LowerBound =
      cast<ConstantInt>(Handle->getArgOperand(1))->getZExtValue();
  uint32_t Size = cast<ConstantInt>(Handle->getArgOperand(2))->getZExtValue();
  uint32_t UpperBound = Size == UINT32_MAX ? UINT32_MAX : LowerBound + Size - 1;

  return hlsl::Binding(Class, Space, LowerBound, UpperBound, nullptr);
}

namespace {
/// Helper for propagating the current handle and ptr indices.
struct AccessIndices {
  Value *GetPtrIdx;
  Value *HandleIdx;
  Value *OffsetIdx;

  bool hasGetPtrIdx() { return GetPtrIdx != nullptr; }
  bool hasHandleIdx() { return HandleIdx != nullptr; }
  bool hasOffsetIdx() { return OffsetIdx != nullptr; }
};

/// AccessIndices cached per phi. The values may be placeholder phis that are
/// later folded away (via replaceAllUsesWith) and freed, so track them with
/// value handles rather than raw pointers.
struct TrackedAccessIndices {
  WeakTrackingVH GetPtrIdx;
  WeakTrackingVH HandleIdx;
  WeakTrackingVH OffsetIdx;

  TrackedAccessIndices() = default;
  TrackedAccessIndices(const AccessIndices &AI)
      : GetPtrIdx(AI.GetPtrIdx), HandleIdx(AI.HandleIdx),
        OffsetIdx(AI.OffsetIdx) {}
  operator AccessIndices() const { return {GetPtrIdx, HandleIdx, OffsetIdx}; }
};

using PhiAccessIndicesMap = SmallDenseMap<PHINode *, TrackedAccessIndices>;
} // namespace

// Compute the total byte offset described by a GEP as a single i32 value,
// handling both constant and variable indices.
static Value *accumulateGEPOffset(GetElementPtrInst *GEP,
                                  IRBuilder<> &Builder) {
  const DataLayout &DL = GEP->getDataLayout();
  unsigned BitWidth = DL.getIndexTypeSizeInBits(GEP->getType());
  SmallMapVector<Value *, APInt, 4> VariableOffsets;
  APInt ConstantOffset(BitWidth, 0);
  bool Success =
      GEP->collectOffset(DL, BitWidth, VariableOffsets, ConstantOffset);
  assert(Success && "Unhandled GEP structure for resource access");
  (void)Success;

  Type *I32 = Builder.getInt32Ty();
  Value *Offset = ConstantInt::get(I32, ConstantOffset.getSExtValue());
  for (auto &[V, Scale] : VariableOffsets) {
    Value *Index = Builder.CreateSExtOrTrunc(V, I32);
    if (!Scale.isOne())
      Index =
          Builder.CreateMul(Index, ConstantInt::get(I32, Scale.getSExtValue()));
    Offset = Builder.CreateAdd(Offset, Index);
  }
  return Offset;
}

// getAccessIndices traverses up the control flow that a ptr came from and
// propagates back the indicies used to access the resource (AccessIndices):
//
//  - GetPtrIdx is the index of dx.resource.getpointer
//  - HandleIdx is the index of dx.resource.handlefrom.*
//  - OffsetIdx is the accumulated byte offset of any GEPs in the ptr chain
static AccessIndices
getAccessIndices(Instruction *I, SmallSetVector<Instruction *, 16> &DeadInsts,
                 PhiAccessIndicesMap &VisitedPhis) {
  if (auto *II = dyn_cast<IntrinsicInst>(I)) {
    if (llvm::is_contained(HandleIntrins, II->getIntrinsicID())) {
      DeadInsts.insert(II);
      return {nullptr, II->getArgOperand(/*Index=*/3), nullptr};
    }

    Intrinsic::ID IID = II->getIntrinsicID();
    if (IID == Intrinsic::dx_resource_getpointer ||
        IID == Intrinsic::dx_resource_getbasepointer) {
      auto *V = dyn_cast<Instruction>(II->getArgOperand(/*Handle=*/0));
      auto AccessIdx = getAccessIndices(V, DeadInsts, VisitedPhis);
      assert(!AccessIdx.hasGetPtrIdx() &&
             "Encountered multiple dx.resource.getpointers in ptr chain?");
      IRBuilder<> Builder(II);
      AccessIdx.GetPtrIdx = ConstantInt::get(Builder.getInt32Ty(), 0);
      if (IID == Intrinsic::dx_resource_getpointer)
        AccessIdx.GetPtrIdx = II->getArgOperand(1);

      DeadInsts.insert(II);
      return AccessIdx;
    }
  }

  if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) {
    auto *V = dyn_cast<Instruction>(GEP->getPointerOperand());
    auto AccessIdx = getAccessIndices(V, DeadInsts, VisitedPhis);

    IRBuilder<> Builder(GEP);
    Value *GEPOffset = accumulateGEPOffset(GEP, Builder);
    AccessIdx.OffsetIdx =
        AccessIdx.hasOffsetIdx()
            ? Builder.CreateAdd(AccessIdx.OffsetIdx, GEPOffset)
            : GEPOffset;

    DeadInsts.insert(GEP);
    return AccessIdx;
  }

  if (auto *Phi = dyn_cast<PHINode>(I)) {
    // If we're already building indices for this phi, return a ref to the phi
    if (auto It = VisitedPhis.find(Phi); It != VisitedPhis.end())
      return It->second;

    unsigned NumEdges = Phi->getNumIncomingValues();
    assert(NumEdges != 0 && "Malformed Phi Node");

    IRBuilder<> Builder(Phi);
    std::unique_ptr<PHINode> GetPtrPhi(
        PHINode::Create(Builder.getInt32Ty(), NumEdges));
    std::unique_ptr<PHINode> HandlePhi(
        PHINode::Create(Builder.getInt32Ty(), NumEdges));
    std::unique_ptr<PHINode> OffsetPhi(
        PHINode::Create(Builder.getInt32Ty(), NumEdges));
    bool HasOffset = false;

    // Register a ref to this phi for a recursive phi. If a placeholder phi
    // below folds to a single value, replaceAllUsesWith updates any cached
    // entries that captured it.
    if (Phi->getType()->isTargetExtTy())
      VisitedPhis[Phi] = AccessIndices{/*GetPtrIdx=*/nullptr, HandlePhi.get(),
                                       /*OffsetIdx=*/nullptr};
    else if (Phi->getType()->isPointerTy())
      VisitedPhis[Phi] =
          AccessIndices{GetPtrPhi.get(), HandlePhi.get(), OffsetPhi.get()};

    for (unsigned Idx = 0; Idx < NumEdges; Idx++) {
      auto *BB = Phi->getIncomingBlock(Idx);
      auto *V = dyn_cast<Instruction>(Phi->getIncomingValue(Idx));
      auto AccessIdx = getAccessIndices(V, DeadInsts, VisitedPhis);
      if (AccessIdx.hasGetPtrIdx())
        GetPtrPhi->addIncoming(AccessIdx.GetPtrIdx, BB);
      HandlePhi->addIncoming(AccessIdx.HandleIdx, BB);
      if (AccessIdx.hasOffsetIdx()) {
        OffsetPhi->addIncoming(AccessIdx.OffsetIdx, BB);
        HasOffset = true;
      } else {
        OffsetPhi->addIncoming(ConstantInt::get(Builder.getInt32Ty(), 0), BB);
      }
    }

    Value *GetPtrIdx;
    if (GetPtrPhi->getNumIncomingValues() == 0) {
      GetPtrIdx = nullptr;
    } else if (Value *ConstantGetPtr = GetPtrPhi->hasConstantValue()) {
      GetPtrIdx = ConstantGetPtr;
      GetPtrPhi->replaceAllUsesWith(GetPtrIdx);
    } else {
      GetPtrIdx = GetPtrPhi.release();
      Builder.Insert(GetPtrIdx);
    }

    Value *HandleIdx;
    if (Value *ConstantHandle = HandlePhi->hasConstantValue()) {
      HandleIdx = ConstantHandle;
      HandlePhi->replaceAllUsesWith(HandleIdx);
    } else {
      HandleIdx = HandlePhi.release();
      Builder.Insert(HandleIdx);
    }

    Value *OffsetIdx = nullptr;
    if (HasOffset) {
      if (Value *ConstantIdx = OffsetPhi->hasConstantValue()) {
        OffsetIdx = ConstantIdx;
        OffsetPhi->replaceAllUsesWith(OffsetIdx);
      } else {
        OffsetIdx = OffsetPhi.release();
        Builder.Insert(OffsetIdx);
      }
    }

    // Replace the placeholder entry with the final indices.
    AccessIndices Result = {GetPtrIdx, HandleIdx, OffsetIdx};
    VisitedPhis[Phi] = Result;
    DeadInsts.insert(Phi);
    return Result;
  }

  if (auto *Select = dyn_cast<SelectInst>(I)) {
    auto *TrueV = dyn_cast<Instruction>(Select->getTrueValue());
    auto TrueAccessIdx = getAccessIndices(TrueV, DeadInsts, VisitedPhis);

    auto *FalseV = dyn_cast<Instruction>(Select->getFalseValue());
    auto FalseAccessIdx = getAccessIndices(FalseV, DeadInsts, VisitedPhis);

    IRBuilder<> Builder(Select);
    Value *GetPtrSelect = nullptr;
    Value *OffsetSelect = nullptr;

    if (TrueAccessIdx.hasGetPtrIdx() && FalseAccessIdx.hasGetPtrIdx())
      GetPtrSelect =
          Builder.CreateSelect(Select->getCondition(), TrueAccessIdx.GetPtrIdx,
                               FalseAccessIdx.GetPtrIdx, "", Select);

    auto *HandleSelect =
        Builder.CreateSelect(Select->getCondition(), TrueAccessIdx.HandleIdx,
                             FalseAccessIdx.HandleIdx, "", Select);

    if (TrueAccessIdx.hasOffsetIdx() || FalseAccessIdx.hasOffsetIdx()) {
      Value *Zero = ConstantInt::get(Builder.getInt32Ty(), 0);
      Value *TrueOffset =
          TrueAccessIdx.hasOffsetIdx() ? TrueAccessIdx.OffsetIdx : Zero;
      Value *FalseOffset =
          FalseAccessIdx.hasOffsetIdx() ? FalseAccessIdx.OffsetIdx : Zero;
      OffsetSelect = Builder.CreateSelect(Select->getCondition(), TrueOffset,
                                          FalseOffset, "", Select);
    }

    DeadInsts.insert(Select);
    return {GetPtrSelect, HandleSelect, OffsetSelect};
  }

  llvm_unreachable("collectUsedHandles should assure this does not occur");
}

static void
replaceHandleWithIndices(Instruction *Ptr, IntrinsicInst *OldHandle,
                         SmallSetVector<Instruction *, 16> &DeadInsts,
                         PhiAccessIndicesMap &VisitedPhis) {
  auto AccessIdx = getAccessIndices(Ptr, DeadInsts, VisitedPhis);
  assert(AccessIdx.hasHandleIdx() &&
         "Couldn't retrieve handle index. This is guaranteed by "
         "getAccessIndices");

  IRBuilder<> Builder(Ptr);
  if (isa<PHINode>(Ptr))
    Builder.SetInsertPoint(Ptr->getParent()->getFirstNonPHIIt());
  IntrinsicInst *Handle = cast<IntrinsicInst>(OldHandle->clone());
  Handle->setArgOperand(/*Index=*/3, AccessIdx.HandleIdx);
  Builder.Insert(Handle);

  if (Ptr->getType()->isPointerTy()) {
    assert(AccessIdx.hasGetPtrIdx() &&
           "Couldn't retrieve getpointer index. This is guaranteed by "
           "getAccessIndices");
    auto *GetPtr = Builder.CreateIntrinsic(Ptr->getType(),
                                           Intrinsic::dx_resource_getpointer,
                                           {Handle, AccessIdx.GetPtrIdx});

    // Reapply any byte offset that came from GEPs in the original ptr chain so
    // that later access lowering still sees it.
    Value *Result = GetPtr;
    if (AccessIdx.hasOffsetIdx())
      Result = Builder.CreatePtrAdd(GetPtr, AccessIdx.OffsetIdx);
    Ptr->replaceAllUsesWith(Result);
  } else {
    assert(Ptr->getType()->isTargetExtTy() && !AccessIdx.hasGetPtrIdx() &&
           "Unexpected resource access operand type");
    Ptr->replaceAllUsesWith(Handle);
  }

  DeadInsts.insert(Ptr);
}

// Try to legalize dx.resource.handlefrom.*.binding and dx.resource.getpointer
// calls with their respective index values and propagate the index values to
// be used at resource access.
//
// If it can't be transformed to be legal then:
//
// Reports an error if a resource access is not guaranteed into a unique global
// resource.
//
// Returns true if any changes are made.
static bool legalizeResourceHandles(Function &F, DXILResourceTypeMap &DRTM) {
  SmallSetVector<Instruction *, 16> DeadInsts;
  PhiAccessIndicesMap VisitedPhis;

  for (BasicBlock &BB : make_early_inc_range(F)) {
    for (Instruction &I : BB) {
      if (auto *HandleOp = getHandleOperand(&I)) {
        SmallVector<IntrinsicInst *> Handles = collectUsedHandles(HandleOp);
        unsigned NumHandles = Handles.size();
        if (NumHandles <= 1)
          continue; // Legal, no-replacement required

        bool SameGlobalBinding = true;
        hlsl::Binding B = getHandleIntrinsicBinding(Handles[0], DRTM);
        for (unsigned Idx = 1; Idx < NumHandles; Idx++)
          SameGlobalBinding &=
              (B == getHandleIntrinsicBinding(Handles[Idx], DRTM));

        if (!SameGlobalBinding)
          diagnoseNonUniqueResourceAccess(&I, Handles);

        replaceHandleWithIndices(getHandleRoot(HandleOp), Handles[0], DeadInsts,
                                 VisitedPhis);
      }
    }
  }

  bool MadeChanges = false;

  // Set up the phis to track if they are erased below
  SmallVector<WeakTrackingVH> ResourcePhis;
  for (const auto &HandleToIndex : VisitedPhis)
    ResourcePhis.push_back(HandleToIndex.first);

  for (auto *I : llvm::reverse(DeadInsts))
    if (I->hasNUses(0)) { // Handle can still be used outside of replaced path
      I->eraseFromParent();
      MadeChanges = true;
    }

  // Any remaining phi nodes are now looped with another phi node and have no
  // other uses
  for (WeakTrackingVH &VH : ResourcePhis)
    if (VH) // True if not removed above or already in this loop
      MadeChanges |= RecursivelyDeleteDeadPHINode(cast<PHINode>(VH));

  return MadeChanges;
}

static void replaceAccess(IntrinsicInst *II, dxil::ResourceTypeInfo &RTI) {
  SmallVector<User *> Worklist;
  for (User *U : II->users())
    Worklist.push_back(U);

  SmallVector<Instruction *> DeadInsts;
  while (!Worklist.empty()) {
    User *U = Worklist.back();
    Worklist.pop_back();

    if (auto *GEP = dyn_cast<GetElementPtrInst>(U)) {
      for (User *U : GEP->users())
        Worklist.push_back(U);
      DeadInsts.push_back(GEP);

    } else if (auto *SI = dyn_cast<StoreInst>(U)) {
      assert(SI->getValueOperand() != II && "Pointer escaped!");
      createStoreIntrinsic(II, SI, RTI);
      DeadInsts.push_back(SI);

    } else if (auto *LI = dyn_cast<LoadInst>(U)) {
      createLoadIntrinsic(II, LI, RTI);
      DeadInsts.push_back(LI);
    } else if (auto *AI = dyn_cast<AtomicRMWInst>(U)) {
      createAtomicBinOpIntrinsic(II, AI, RTI);
      DeadInsts.push_back(AI);
    } else if (auto *CXI = dyn_cast<AtomicCmpXchgInst>(U)) {
      createAtomicCompareExchangeIntrinsic(II, CXI, RTI);
      DeadInsts.push_back(CXI);
    } else
      llvm_unreachable("Unhandled instruction - pointer escaped?");
  }

  // Traverse the now-dead instructions in RPO and remove them.
  for (Instruction *Dead : llvm::reverse(DeadInsts))
    Dead->eraseFromParent();
  II->eraseFromParent();
}

static bool transformResourcePointers(Function &F, DXILResourceTypeMap &DRTM) {
  SmallVector<std::pair<IntrinsicInst *, dxil::ResourceTypeInfo>> Resources;
  for (BasicBlock &BB : make_early_inc_range(F))
    for (Instruction &I : BB)
      if (auto *II = dyn_cast<IntrinsicInst>(&I))
        if (II->getIntrinsicID() == Intrinsic::dx_resource_getpointer ||
            II->getIntrinsicID() == Intrinsic::dx_resource_getbasepointer) {
          auto *HandleTy = cast<TargetExtType>(II->getArgOperand(0)->getType());
          assert(
              (DRTM[HandleTy].isCBuffer() ||
               II->getIntrinsicID() != Intrinsic::dx_resource_getbasepointer) &&
              "dx_resource_getbasepointer should only be used by cbuffers");
          Resources.emplace_back(II, DRTM[HandleTy]);
        }

  for (auto &[II, RI] : Resources)
    replaceAccess(II, RI);

  return !Resources.empty();
}

PreservedAnalyses DXILResourceAccess::run(Function &F,
                                          FunctionAnalysisManager &FAM) {
  auto &MAMProxy = FAM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
  DXILResourceTypeMap *DRTM =
      MAMProxy.getCachedResult<DXILResourceTypeAnalysis>(*F.getParent());
  assert(DRTM && "DXILResourceTypeAnalysis must be available");

  bool MadeHandleChanges = legalizeResourceHandles(F, *DRTM);
  bool MadeResourceChanges = transformResourcePointers(F, *DRTM);
  if (!(MadeHandleChanges || MadeResourceChanges))
    return PreservedAnalyses::all();

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

namespace {
class DXILResourceAccessLegacy : public FunctionPass {
public:
  bool runOnFunction(Function &F) override {
    DXILResourceTypeMap &DRTM =
        getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
    bool MadeHandleChanges = legalizeResourceHandles(F, DRTM);
    bool MadeResourceChanges = transformResourcePointers(F, DRTM);
    return MadeHandleChanges || MadeResourceChanges;
  }
  StringRef getPassName() const override { return "DXIL Resource Access"; }
  DXILResourceAccessLegacy() : FunctionPass(ID) {}

  static char ID; // Pass identification.
  void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
    AU.addRequired<DXILResourceTypeWrapperPass>();
  }
};
char DXILResourceAccessLegacy::ID = 0;
} // end anonymous namespace

INITIALIZE_PASS_BEGIN(DXILResourceAccessLegacy, DEBUG_TYPE,
                      "DXIL Resource Access", false, false)
INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass)
INITIALIZE_PASS_END(DXILResourceAccessLegacy, DEBUG_TYPE,
                    "DXIL Resource Access", false, false)

FunctionPass *llvm::createDXILResourceAccessLegacyPass() {
  return new DXILResourceAccessLegacy();
}
