[llvm] [DirectX] Prevent `dxil-resource-access` from inserting a resource access in-between phi nodes (PR #211343)

Finn Plummer via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 4 09:53:34 PDT 2026


https://github.com/inbelic updated https://github.com/llvm/llvm-project/pull/211343

>From 9b2b0c4fa7ead5f5cf528cae30d67b14dc0df17b Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Tue, 21 Jul 2026 23:25:26 +0000
Subject: [PATCH] prevent inserting the resource access in-between phi nodes

---
 .../lib/Target/DirectX/DXILResourceAccess.cpp |  2 ++
 .../ResourceAccess/phi-insert-point.ll        | 36 +++++++++++++++++++
 2 files changed, 38 insertions(+)
 create mode 100644 llvm/test/CodeGen/DirectX/ResourceAccess/phi-insert-point.ll

diff --git a/llvm/lib/Target/DirectX/DXILResourceAccess.cpp b/llvm/lib/Target/DirectX/DXILResourceAccess.cpp
index 25d860e615c17..3ff525f132fd4 100644
--- a/llvm/lib/Target/DirectX/DXILResourceAccess.cpp
+++ b/llvm/lib/Target/DirectX/DXILResourceAccess.cpp
@@ -704,6 +704,8 @@ replaceHandleWithIndices(Instruction *Ptr, IntrinsicInst *OldHandle,
          "Couldn't retrieve indices. 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);
diff --git a/llvm/test/CodeGen/DirectX/ResourceAccess/phi-insert-point.ll b/llvm/test/CodeGen/DirectX/ResourceAccess/phi-insert-point.ll
new file mode 100644
index 0000000000000..40fb518c8358e
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ResourceAccess/phi-insert-point.ll
@@ -0,0 +1,36 @@
+; RUN: opt -S -dxil-resource-type -dxil-resource-access \
+; RUN:  -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
+
+; Regression test for handle resolution when the resource pointer being replaced
+; is itself a PHI node that shares its block with a sibling PHI surviving the
+; transform.
+
+ at OutArr.str = internal unnamed_addr constant [7 x i8] c"OutArr\00", align 1
+
+; CHECK-LABEL: ptr_phi_before_sibling_phi(
+; CHECK-SAME:   i1 %[[COND:.*]], i32 %[[A:.*]], i32 %[[B:.*]])
+define i32 @ptr_phi_before_sibling_phi(i1 %cond, i32 %a, i32 %b) {
+; CHECK-NOT: handlefromimplicitbinding
+entry:
+  %handle0 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_i32_1_0t(i32 2, i32 0, i32 -1, i32 0, ptr nonnull @OutArr.str)
+  %ptr0 = tail call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_1_0t(target("dx.RawBuffer", i32, 1, 0) %handle0, i32 %a)
+  br i1 %cond, label %if.then.i, label %main
+
+if.then.i:
+  %handle1 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_i32_1_0t(i32 2, i32 0, i32 -1, i32 1, ptr nonnull @OutArr.str)
+  %ptr1 = tail call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_1_0t(target("dx.RawBuffer", i32, 1, 0) %handle1, i32 %b)
+  br label %main
+
+main:
+; CHECK:     main:
+; CHECK-NEXT:  %[[C:.*]] = phi i32 [ %[[A]], %entry ], [ %[[B]], %if.then.i ]
+; CHECK-NEXT:  %[[IDX:.*]] = phi i32 [ 0, %entry ], [ 1, %if.then.i ]
+; CHECK-NEXT:  %[[SIBLING:.*]] = phi i32 [ %[[A]], %entry ], [ %[[B]], %if.then.i ]
+; CHECK-NEXT:  %[[HANDLE:.*]] = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_i32_1_0t(i32 2, i32 0, i32 -1, i32 %[[IDX]], ptr nonnull @OutArr.str)
+; CHECK-NEXT:  call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_i32_1_0t.i32(target("dx.RawBuffer", i32, 1, 0) %[[HANDLE]], i32 %[[C]], i32 0, i32 %[[SIBLING]])
+; CHECK-NEXT:  ret i32 %[[SIBLING]]
+  %ptr_phi = phi ptr [ %ptr0, %entry ], [ %ptr1, %if.then.i ]
+  %sibling = phi i32 [ %a, %entry ], [ %b, %if.then.i ]
+  store i32 %sibling, ptr %ptr_phi, align 4
+  ret i32 %sibling
+}



More information about the llvm-commits mailing list