[llvm] [DirectX] Legalize memcpy (PR #139173)

Deric C. via llvm-commits llvm-commits at lists.llvm.org
Thu May 15 12:59:53 PDT 2025


================
@@ -246,6 +246,61 @@ downcastI64toI32InsertExtractElements(Instruction &I,
   }
 }
 
+static void emitMemcpyExpansion(IRBuilder<> &Builder, Value *Dst, Value *Src,
+                                ConstantInt *Length) {
+
+  uint64_t ByteLength = Length->getZExtValue();
+  if (ByteLength == 0)
+    return;
+
+  LLVMContext &Ctx = Builder.getContext();
+  const DataLayout &DL = Builder.GetInsertBlock()->getModule()->getDataLayout();
+
+  auto GetArrTyFromVal = [](Value *Val) -> ArrayType * {
+    assert(isa<AllocaInst>(Val) ||
+           isa<GlobalVariable>(Val) &&
+               "Expected Val to be an Alloca or Global Variable");
+    if (auto *Alloca = dyn_cast<AllocaInst>(Val))
+      return dyn_cast<ArrayType>(Alloca->getAllocatedType());
+    if (auto *GlobalVar = dyn_cast<GlobalVariable>(Val))
+      return dyn_cast<ArrayType>(GlobalVar->getValueType());
+    return nullptr;
+  };
+
+  ArrayType *ArrTy = GetArrTyFromVal(Dst);
+  assert(ArrTy && "Expected Dst of memcpy to be a Pointer to an Array Type");
+  if (auto *DstGlobalVar = dyn_cast<GlobalVariable>(Dst))
+    assert(!DstGlobalVar->isConstant() &&
+           "The Dst of memcpy must not be a constant Global Variable");
+
+  [[maybe_unused]] ArrayType *SrcArrTy = GetArrTyFromVal(Src);
+  assert(SrcArrTy && "Expected Src of memcpy to be a Pointer to an Array Type");
+
+  // This assumption simplifies implementation and covers currently-known
+  // use-cases for DXIL. It may be relaxed in the future if required.
+  assert(ArrTy == SrcArrTy &&
+         "Array Types of Src and Dst in memcpy must match");
+
+  Type *ElemTy = ArrTy->getElementType();
+  uint64_t ElemSize = DL.getTypeStoreSize(ElemTy);
+  assert(ElemSize > 0 && "Size must be set");
+
+  [[maybe_unused]] uint64_t Size = ArrTy->getArrayNumElements();
+  assert(ElemSize * Size >= ByteLength &&
+         "Array size must be at least as large as the memcpy length");
+
+  uint64_t NumElemsToCopy = ByteLength / ElemSize;
+  assert(ByteLength % ElemSize == 0 &&
+         "memcpy length must be divisible by array element type");
+  for (uint64_t I = 0; I < NumElemsToCopy; ++I) {
+    Value *Offset = ConstantInt::get(Type::getInt32Ty(Ctx), I);
+    Value *SrcPtr = Builder.CreateGEP(ElemTy, Src, Offset, "gep");
----------------
Icohedron wrote:

The asserts do ensure that the GEP is inbounds, so I think it should be fine to set `GEP.isInBounds()` which by definition also implies no unsigned signed wrapping (nusw)

https://github.com/llvm/llvm-project/pull/139173


More information about the llvm-commits mailing list