[llvm] 1411f47 - [DirectX] Lower `llvm.dx.resource.handlefromheap` intrinsic (#216459)

via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 22 11:06:33 PDT 2026


Author: Helena Kotas
Date: 2026-08-22T11:06:28-07:00
New Revision: 1411f47e2297a95ba02419b7cb0fde3ecc89cce2

URL: https://github.com/llvm/llvm-project/commit/1411f47e2297a95ba02419b7cb0fde3ecc89cce2
DIFF: https://github.com/llvm/llvm-project/commit/1411f47e2297a95ba02419b7cb0fde3ecc89cce2.diff

LOG: [DirectX] Lower `llvm.dx.resource.handlefromheap` intrinsic (#216459)

Add lowering of `llvm.dx.resource.handlefromheap` intrinsic. It gets
translated to DXIL ops `createHandleFromHeap` and `annotateHandle`.

For example, the intrinsic call

```llvm
%typed = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
    @llvm.dx.resource.handlefromheap.tdx.TypedBuffer_v4f32_1_0_0(i32 3)
```

will lower to

```llvm
%0 = call %dx.types.Handle @dx.op.createHandleFromHeap(i32 218, i32 3, i1 false, i1 false)
%1 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %0,
         %dx.types.ResourceProperties { i32 4106, i32 1033 })
```

The value of non-uniform index flag is calculated using existing
`hasNonUniformIndex` helper function.

Fixes #91406

Added: 
    llvm/test/CodeGen/DirectX/CreateHandleHeap-NURI.ll
    llvm/test/CodeGen/DirectX/CreateHandleHeap.ll

Modified: 
    llvm/lib/Target/DirectX/DXIL.td
    llvm/lib/Target/DirectX/DXILOpLowering.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td
index bbf7cddb5c17c..4beafd0c619b0 100644
--- a/llvm/lib/Target/DirectX/DXIL.td
+++ b/llvm/lib/Target/DirectX/DXIL.td
@@ -1531,3 +1531,11 @@ def CreateHandleFromBinding : DXILOp<217, createHandleFromBinding> {
   let stages = [Stages<DXIL1_6, [all_stages]>];
   let attributes = [Attributes<DXIL1_0, [ReadNone]>];
 }
+
+def CreateHandleFromHeap : DXILOp<218, createHandleFromHeap> {
+  let Doc = "create resource handle from heap";
+  let arguments = [Int32Ty, Int1Ty, Int1Ty];
+  let result = HandleTy;
+  let stages = [Stages<DXIL1_6, [all_stages]>];
+  let attributes = [Attributes<DXIL1_0, [ReadNone]>];
+}

diff  --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
index dc15c02481468..12f80d66f0333 100644
--- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
@@ -433,6 +433,49 @@ class OpLowerer {
     return lowerToBindAndAnnotateHandle(F);
   }
 
+  bool lowerHandleFromHeap(Function &F) {
+    IRBuilder<> &IRB = OpBuilder.getIRB();
+
+    return replaceFunction(F, [&](CallInst *CI) -> Error {
+      IRB.SetInsertPoint(CI);
+
+      auto *It = DRM.find(CI);
+      assert(It != DRM.end() && "Resource not in map?");
+      dxil::ResourceInfo &RI = *It;
+      dxil::ResourceTypeInfo &RTI = DRTM[RI.getHandleTy()];
+
+      Value *IndexOp = CI->getArgOperand(0);
+      Value *IsSamplerHeap =
+          ConstantInt::getBool(IRB.getContext(), RTI.isSampler());
+
+      std::pair<uint32_t, uint32_t> Props =
+          RI.getAnnotateProps(*F.getParent(), RTI);
+
+      bool NonUniformIndex = hasNonUniformIndex(IndexOp);
+      Value *NonUniformOp =
+          ConstantInt::getBool(IRB.getContext(), NonUniformIndex);
+
+      std::array<Value *, 3> Args{IndexOp, IsSamplerHeap, NonUniformOp};
+      Expected<CallInst *> OpCreateHandle = OpBuilder.tryCreateOp(
+          OpCode::CreateHandleFromHeap, Args, CI->getName());
+      if (Error E = OpCreateHandle.takeError())
+        return E;
+
+      std::array<Value *, 2> AnnotateArgs{
+          *OpCreateHandle, OpBuilder.getResProps(Props.first, Props.second)};
+      Expected<CallInst *> OpAnnotate = OpBuilder.tryCreateOp(
+          OpCode::AnnotateHandle, AnnotateArgs,
+          CI->hasName() ? CI->getName() + "_annot" : Twine());
+      if (Error E = OpAnnotate.takeError())
+        return E;
+
+      Value *Cast = createTmpHandleCast(*OpAnnotate, CI->getType());
+      CI->replaceAllUsesWith(Cast);
+      CI->eraseFromParent();
+      return Error::success();
+    });
+  }
+
   /// Replace uses of \c Intrin with the values in the `dx.ResRet` of \c Op.
   /// Since we expect to be post-scalarization, make an effort to avoid vectors.
   Error replaceResRetUses(CallInst *Intrin, CallInst *Op, bool HasCheckBit) {
@@ -1281,6 +1324,9 @@ class OpLowerer {
       case Intrinsic::dx_resource_handlefrombinding:
         HasErrors |= lowerHandleFromBinding(F);
         break;
+      case Intrinsic::dx_resource_handlefromheap:
+        HasErrors |= lowerHandleFromHeap(F);
+        break;
       case Intrinsic::dx_resource_getbasepointer:
       case Intrinsic::dx_resource_getpointer:
         HasErrors |= lowerGetPointer(F);

diff  --git a/llvm/test/CodeGen/DirectX/CreateHandleHeap-NURI.ll b/llvm/test/CodeGen/DirectX/CreateHandleHeap-NURI.ll
new file mode 100644
index 0000000000000..54bd7c7fd08f6
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/CreateHandleHeap-NURI.ll
@@ -0,0 +1,32 @@
+; RUN: opt -S -passes=dxil-op-lower %s | FileCheck %s
+
+target triple = "dxil-pc-shadermodel6.6-compute"
+
+declare i32 @some_val();
+
+define void @test_with_nuri() {
+
+  %val = call i32 @some_val()
+
+  ; int val = some_val();
+  ; RWBuffer<float4> Buf = ResourceDescriptorHeap[NonUniformResourceIndex(val)]
+  %nuri = tail call noundef i32 @llvm.dx.resource.nonuniformindex(i32 %val)
+  %typed0 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
+              @llvm.dx.resource.handlefromheap.tdx.TypedBuffer_v4f32_1_0_0(i32 %nuri)
+  ; CHECK: [[HANDLE0:%.*]] = call %dx.types.Handle @dx.op.createHandleFromHeap(i32 218, i32 %val, i1 false, i1 true)
+  ; CHECK: [[ANNOT_HANDLE0:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[HANDLE0]], %dx.types.ResourceProperties { i32 4106, i32 1033 })
+
+  ; SamplerState Samp = SamplerDescriptorHeap[NonUniformResourceIndex(val + 1) % 10];
+  %add1 = add i32 %val, 1
+  %nuri2 = tail call noundef i32 @llvm.dx.resource.nonuniformindex(i32 %add1)
+  %rem1 = urem i32 %nuri2, 10
+  %samp = call target("dx.Sampler", 0)
+              @llvm.dx.resource.handlefromheap.tdx.Sampler_0(i32 %rem1)
+  ; CHECK: [[HANDLE1:%.*]] = call %dx.types.Handle @dx.op.createHandleFromHeap(i32 218, i32 %rem1, i1 true, i1 true)
+  ; CHECK: [[ANNOT_HANDLE1:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[HANDLE1]], %dx.types.ResourceProperties { i32 14, i32 0 })
+
+  ret void
+}
+
+; CHECK: declare %dx.types.Handle @dx.op.createHandleFromHeap(i32, i32, i1, i1)
+; CHECK: declare %dx.types.Handle @dx.op.annotateHandle(i32, %dx.types.Handle, %dx.types.ResourceProperties)

diff  --git a/llvm/test/CodeGen/DirectX/CreateHandleHeap.ll b/llvm/test/CodeGen/DirectX/CreateHandleHeap.ll
new file mode 100644
index 0000000000000..8f432b3a018df
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/CreateHandleHeap.ll
@@ -0,0 +1,32 @@
+; RUN: opt -S -passes=dxil-op-lower %s | FileCheck %s
+
+target triple = "dxil-pc-shadermodel6.6-compute"
+
+declare i32 @some_val();
+
+define void @test() {
+  ; RWBuffer<float4> Buf = ResourceDescriptorHeap[3]
+  %typed = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
+              @llvm.dx.resource.handlefromheap.tdx.TypedBuffer_v4f32_1_0_0(i32 3)
+  ; CHECK: [[HANDLE0:%.*]] = call %dx.types.Handle @dx.op.createHandleFromHeap(i32 218, i32 3, i1 false, i1 false)
+  ; CHECK: [[ANNOT_HANDLE0:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[HANDLE0]], %dx.types.ResourceProperties { i32 4106, i32 1033 })
+
+  ; int val = some_val();
+  ; RWBuffer<float4> Buf = ResourceDescriptorHeap[val]
+  %val = call i32 @some_val()
+  %typed1 = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
+              @llvm.dx.resource.handlefromheap.tdx.TypedBuffer_v4f32_1_0_0(i32 %val)
+  ; CHECK: [[HANDLE1:%.*]] = call %dx.types.Handle @dx.op.createHandleFromHeap(i32 218, i32 %val, i1 false, i1 false)
+  ; CHECK: [[ANNOT_HANDLE1:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[HANDLE1]], %dx.types.ResourceProperties { i32 4106, i32 1033 })
+
+  ; SamplerState Samp = SamplerDescriptorHeap[val];
+  %samp = call target("dx.Sampler", 0)
+              @llvm.dx.resource.handlefromheap.tdx.Sampler_0(i32 %val)
+  ; CHECK: [[HANDLE2:%.*]] = call %dx.types.Handle @dx.op.createHandleFromHeap(i32 218, i32 %val, i1 true, i1 false)
+  ; CHECK: [[ANNOT_HANDLE2:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[HANDLE2]], %dx.types.ResourceProperties { i32 14, i32 0 })
+
+  ret void
+}
+
+; CHECK: declare %dx.types.Handle @dx.op.createHandleFromHeap(i32, i32, i1, i1)
+; CHECK: declare %dx.types.Handle @dx.op.annotateHandle(i32, %dx.types.Handle, %dx.types.ResourceProperties)


        


More information about the llvm-commits mailing list