[llvm] [DirectX] Mark `dx.resource.getpointer` as convergent (PR #182099)

Finn Plummer via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 19 10:55:49 PST 2026


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

>From 6e6c6278895a68e50809e8ee437c195880193174 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Thu, 12 Feb 2026 13:47:19 -0800
Subject: [PATCH 1/3] [DX] Mark `dx.resource.getpointer` as convergent

- This prevents unwanted optimizations occuring around resource access
- Add tests to show prevention of sinking handle retrieval for
GVN/SimplifyCFG cases
---
 llvm/include/llvm/IR/IntrinsicsDirectX.td     |   2 +-
 .../Transforms/GVN/no-sink-dxgetpointer.ll    | 100 +++++++++++++
 .../DirectX/no-sink-dxgetpointer.ll           | 131 ++++++++++++++++++
 3 files changed, 232 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/Transforms/GVN/no-sink-dxgetpointer.ll
 create mode 100644 llvm/test/Transforms/SimplifyCFG/DirectX/no-sink-dxgetpointer.ll

diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index 5bf8a785d528c..79f1586d12ead 100644
--- a/llvm/include/llvm/IR/IntrinsicsDirectX.td
+++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td
@@ -38,7 +38,7 @@ def int_dx_resource_handlefromimplicitbinding
 
 def int_dx_resource_getpointer
     : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [llvm_any_ty, llvm_i32_ty],
-                            [IntrNoMem]>;
+                            [IntrConvergent, IntrNoMem]>;
 
 def int_dx_resource_nonuniformindex
     : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>;
diff --git a/llvm/test/Transforms/GVN/no-sink-dxgetpointer.ll b/llvm/test/Transforms/GVN/no-sink-dxgetpointer.ll
new file mode 100644
index 0000000000000..4537d5f1abc88
--- /dev/null
+++ b/llvm/test/Transforms/GVN/no-sink-dxgetpointer.ll
@@ -0,0 +1,100 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes=gvn -S %s | FileCheck %s
+
+; This test ensures that given dx.resource.getpointer is marked convergent, the
+; GVN pass is prevented from sinking these intrinsics.
+;
+; NOTE: The following ir represents case F and G from:
+; https://godbolt.org/z/cK4xh1P49.
+
+%"class.hlsl::RWBuffer" = type { target("dx.TypedBuffer", i32, 1, 0, 1) }
+%"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", i32, 1, 0), target("dx.RawBuffer", i32, 1, 0) }
+%__cblayout_c = type <{ i32 }>
+
+ at In = internal global %"class.hlsl::RWBuffer" poison, align 4
+ at .str = private unnamed_addr constant [3 x i8] c"In\00", align 1
+ at Out0 = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4
+ at .str.2 = private unnamed_addr constant [5 x i8] c"Out0\00", align 1
+ at Out1 = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4
+ at .str.4 = private unnamed_addr constant [5 x i8] c"Out1\00", align 1
+ at c.cb = local_unnamed_addr global target("dx.CBuffer", %__cblayout_c) poison
+ at cond = external hidden local_unnamed_addr addrspace(2) global i32, align 4
+ at c.str = private unnamed_addr constant [2 x i8] c"c\00", align 1
+
+define void @main() local_unnamed_addr {
+; CHECK-LABEL: define void @main() local_unnamed_addr {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call target("dx.TypedBuffer", i32, 1, 0, 1) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_i32_1_0_1t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @.str)
+; CHECK-NEXT:    store target("dx.TypedBuffer", i32, 1, 0, 1) [[TMP0]], ptr @In, align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_1_0t(i32 0, i32 1, i32 1, i32 0, ptr nonnull @.str.2)
+; CHECK-NEXT:    store target("dx.RawBuffer", i32, 1, 0) [[TMP1]], ptr @Out0, align 4
+; CHECK-NEXT:    store target("dx.RawBuffer", i32, 1, 0) [[TMP1]], ptr getelementptr inbounds nuw (i8, ptr @Out0, i32 4), align 4
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_1_0t(i32 0, i32 2, i32 1, i32 0, ptr nonnull @.str.4)
+; CHECK-NEXT:    store target("dx.RawBuffer", i32, 1, 0) [[TMP2]], ptr @Out1, align 4
+; CHECK-NEXT:    store target("dx.RawBuffer", i32, 1, 0) [[TMP2]], ptr getelementptr inbounds nuw (i8, ptr @Out1, i32 4), align 4
+; CHECK-NEXT:    [[C_CB_H_I_I:%.*]] = tail call target("dx.CBuffer", [[__CBLAYOUT_C:%.*]]) @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_s___cblayout_cst(i32 4, i32 0, i32 1, i32 0, ptr nonnull @c.str)
+; CHECK-NEXT:    store target("dx.CBuffer", [[__CBLAYOUT_C]]) [[C_CB_H_I_I]], ptr @c.cb, align 4
+; CHECK-NEXT:    [[TMP3:%.*]] = tail call i32 @llvm.dx.flattened.thread.id.in.group()
+; CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr addrspace(2) @cond, align 4
+; CHECK-NEXT:    [[LOADEDV_I:%.*]] = trunc nuw i32 [[TMP4]] to i1
+; CHECK-NEXT:    br i1 [[LOADEDV_I]], label %[[IF_THEN_I:.*]], label %[[IF_ELSE_I:.*]]
+; CHECK:       [[IF_THEN_I]]:
+; CHECK-NEXT:    [[TMP5:%.*]] = tail call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) [[TMP0]], i32 [[TMP3]])
+; CHECK-NEXT:    [[TMP6:%.*]] = load i32, ptr [[TMP5]], align 4
+; CHECK-NEXT:    [[HLSL_WAVE_ACTIVE_SUM_I:%.*]] = tail call i32 @llvm.dx.wave.reduce.sum.i32(i32 [[TMP6]])
+; CHECK-NEXT:    [[TMP7:%.*]] = 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) [[TMP1]], i32 [[TMP3]])
+; CHECK-NEXT:    store i32 [[HLSL_WAVE_ACTIVE_SUM_I]], ptr [[TMP7]], align 4
+; CHECK-NEXT:    br label %[[MAIN_EXIT:.*]]
+; CHECK:       [[IF_ELSE_I]]:
+; CHECK-NEXT:    [[TMP8:%.*]] = tail call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) [[TMP0]], i32 [[TMP3]])
+; CHECK-NEXT:    [[TMP9:%.*]] = load i32, ptr [[TMP8]], align 4
+; CHECK-NEXT:    [[TMP10:%.*]] = 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) [[TMP1]], i32 0)
+; CHECK-NEXT:    store i32 [[TMP9]], ptr [[TMP10]], align 4
+; CHECK-NEXT:    br label %[[MAIN_EXIT]]
+; CHECK:       [[MAIN_EXIT]]:
+; CHECK-NEXT:    [[TMP11:%.*]] = tail call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) [[TMP0]], i32 [[TMP3]])
+; CHECK-NEXT:    [[TMP12:%.*]] = load i32, ptr [[TMP11]], align 4
+; CHECK-NEXT:    [[HLSL_WAVE_ACTIVE_SUM5_I:%.*]] = tail call i32 @llvm.dx.wave.reduce.sum.i32(i32 [[TMP12]])
+; CHECK-NEXT:    [[TMP13:%.*]] = 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) [[TMP1]], i32 [[TMP3]])
+; CHECK-NEXT:    store i32 [[HLSL_WAVE_ACTIVE_SUM5_I]], ptr [[TMP13]], align 4
+; CHECK-NEXT:    ret void
+;
+entry:
+  %0 = tail call target("dx.TypedBuffer", i32, 1, 0, 1) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_i32_1_0_1t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @.str)
+  store target("dx.TypedBuffer", i32, 1, 0, 1) %0, ptr @In, align 4
+  %1 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_1_0t(i32 0, i32 1, i32 1, i32 0, ptr nonnull @.str.2)
+  store target("dx.RawBuffer", i32, 1, 0) %1, ptr @Out0, align 4
+  store target("dx.RawBuffer", i32, 1, 0) %1, ptr getelementptr inbounds nuw (i8, ptr @Out0, i32 4), align 4
+  %2 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_1_0t(i32 0, i32 2, i32 1, i32 0, ptr nonnull @.str.4)
+  store target("dx.RawBuffer", i32, 1, 0) %2, ptr @Out1, align 4
+  store target("dx.RawBuffer", i32, 1, 0) %2, ptr getelementptr inbounds nuw (i8, ptr @Out1, i32 4), align 4
+  %c.cb_h.i.i = tail call target("dx.CBuffer", %__cblayout_c) @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_s___cblayout_cst(i32 4, i32 0, i32 1, i32 0, ptr nonnull @c.str)
+  store target("dx.CBuffer", %__cblayout_c) %c.cb_h.i.i, ptr @c.cb, align 4
+  %3 = tail call i32 @llvm.dx.flattened.thread.id.in.group()
+  %4 = load i32, ptr addrspace(2) @cond, align 4
+  %loadedv.i = trunc nuw i32 %4 to i1
+  br i1 %loadedv.i, label %if.then.i, label %if.else.i
+
+if.then.i:                                        ; preds = %entry
+  %5 = tail call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %0, i32 %3)
+  %6 = load i32, ptr %5, align 4
+  %hlsl.wave.active.sum.i = tail call i32 @llvm.dx.wave.reduce.sum.i32(i32 %6)
+  %7 = 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) %1, i32 %3)
+  store i32 %hlsl.wave.active.sum.i, ptr %7, align 4
+  br label %main.exit
+
+if.else.i:                                        ; preds = %entry
+  %8 = tail call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %0, i32 %3)
+  %9 = load i32, ptr %8, align 4
+  %10 = 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) %1, i32 0)
+  store i32 %9, ptr %10, align 4
+  br label %main.exit
+
+main.exit:                                    ; preds = %if.then.i, %if.else.i
+  %11 = tail call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %0, i32 %3)
+  %12 = load i32, ptr %11, align 4
+  %hlsl.wave.active.sum5.i = tail call i32 @llvm.dx.wave.reduce.sum.i32(i32 %12)
+  %13 = 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) %1, i32 %3)
+  store i32 %hlsl.wave.active.sum5.i, ptr %13, align 4
+  ret void
+}
diff --git a/llvm/test/Transforms/SimplifyCFG/DirectX/no-sink-dxgetpointer.ll b/llvm/test/Transforms/SimplifyCFG/DirectX/no-sink-dxgetpointer.ll
new file mode 100644
index 0000000000000..76ab7bf18f3e2
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/DirectX/no-sink-dxgetpointer.ll
@@ -0,0 +1,131 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes=simplifycfg -S %s | FileCheck %s
+
+; This test ensures that given dx.resource.getpointer is marked convergent, the
+; SimplifyCFG pass will be prevented from moving these intrinsics into the
+; branches required for sinking handle retrieve before resource access.
+;
+; NOTE: The following test ir is generated from:
+; https://godbolt.org/z/1EdGTbscE.
+
+%"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", i32, 1, 0), target("dx.RawBuffer", i32, 1, 0) }
+%__cblayout_d = type <{ i32, i32, i32, i32 }>
+
+ at a = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4
+ at .str = private unnamed_addr constant [2 x i8] c"a\00", align 1
+ at b = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4
+ at .str.2 = private unnamed_addr constant [2 x i8] c"b\00", align 1
+ at c = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4
+ at .str.4 = private unnamed_addr constant [2 x i8] c"c\00", align 1
+ at d.cb = local_unnamed_addr global target("dx.CBuffer", %__cblayout_d) poison
+ at e = external hidden local_unnamed_addr addrspace(2) global i32, align 4
+ at f = external hidden local_unnamed_addr addrspace(2) global i32, align 4
+ at g = external hidden local_unnamed_addr addrspace(2) global i32, align 4
+ at h = external hidden local_unnamed_addr addrspace(2) global i32, align 4
+ at d.str = private unnamed_addr constant [2 x i8] c"d\00", align 1
+
+define void @main() local_unnamed_addr {
+; CHECK-LABEL: define void @main() local_unnamed_addr {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_i32_1_0t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @.str)
+; CHECK-NEXT:    store target("dx.RawBuffer", i32, 1, 0) [[TMP0]], ptr @a, align 4
+; CHECK-NEXT:    store target("dx.RawBuffer", i32, 1, 0) [[TMP0]], ptr getelementptr inbounds nuw (i8, ptr @a, i32 4), align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = 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 @.str.2)
+; CHECK-NEXT:    store target("dx.RawBuffer", i32, 1, 0) [[TMP1]], ptr @b, align 4
+; CHECK-NEXT:    store target("dx.RawBuffer", i32, 1, 0) [[TMP1]], ptr getelementptr inbounds nuw (i8, ptr @b, i32 4), align 4
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_i32_1_0t(i32 4, i32 0, i32 1, i32 0, ptr nonnull @.str.4)
+; CHECK-NEXT:    store target("dx.RawBuffer", i32, 1, 0) [[TMP2]], ptr @c, align 4
+; CHECK-NEXT:    store target("dx.RawBuffer", i32, 1, 0) [[TMP2]], ptr getelementptr inbounds nuw (i8, ptr @c, i32 4), align 4
+; CHECK-NEXT:    [[D_CB_H_I_I:%.*]] = tail call target("dx.CBuffer", [[__CBLAYOUT_D:%.*]]) @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_s___cblayout_dst(i32 6, i32 0, i32 1, i32 0, ptr nonnull @d.str)
+; CHECK-NEXT:    store target("dx.CBuffer", [[__CBLAYOUT_D]]) [[D_CB_H_I_I]], ptr @d.cb, align 4
+; CHECK-NEXT:    [[TMP3:%.*]] = load i32, ptr addrspace(2) @h, align 4
+; CHECK-NEXT:    [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[TMP3]], 0
+; CHECK-NEXT:    br i1 [[TOBOOL_NOT_I]], label %[[IF_ELSE_I:.*]], label %[[IF_THEN_I:.*]]
+; CHECK:       [[IF_THEN_I]]:
+; CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr addrspace(2) @f, align 4
+; CHECK-NEXT:    [[TMP5:%.*]] = 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) [[TMP1]], i32 [[TMP4]])
+; CHECK-NEXT:    [[TMP6:%.*]] = load i32, ptr [[TMP5]], align 4
+; CHECK-NEXT:    [[TMP7:%.*]] = load i32, ptr addrspace(2) @g, align 4
+; CHECK-NEXT:    [[TMP8:%.*]] = 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) [[TMP2]], i32 [[TMP7]])
+; CHECK-NEXT:    store i32 [[TMP6]], ptr [[TMP8]], align 4
+; CHECK-NEXT:    br label %[[MAIN_EXIT:.*]]
+; CHECK:       [[IF_ELSE_I]]:
+; CHECK-NEXT:    [[TMP9:%.*]] = load i32, ptr addrspace(2) @g, align 4
+; CHECK-NEXT:    [[CMP_I:%.*]] = icmp eq i32 [[TMP9]], 0
+; CHECK-NEXT:    br i1 [[CMP_I]], label %[[IF_THEN2_I:.*]], label %[[IF_ELSE6_I:.*]]
+; CHECK:       [[IF_THEN2_I]]:
+; CHECK-NEXT:    [[TMP10:%.*]] = 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) [[TMP1]], i32 0)
+; CHECK-NEXT:    [[TMP11:%.*]] = load i32, ptr [[TMP10]], align 4
+; CHECK-NEXT:    [[TMP12:%.*]] = 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) [[TMP2]], i32 0)
+; CHECK-NEXT:    store i32 [[TMP11]], ptr [[TMP12]], align 4
+; CHECK-NEXT:    br label %[[MAIN_EXIT]]
+; CHECK:       [[IF_ELSE6_I]]:
+; CHECK-NEXT:    [[TMP13:%.*]] = load i32, ptr addrspace(2) @e, align 4
+; CHECK-NEXT:    [[TMP14:%.*]] = 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) [[TMP0]], i32 [[TMP13]])
+; CHECK-NEXT:    [[TMP15:%.*]] = load i32, ptr [[TMP14]], align 4
+; CHECK-NEXT:    [[TMP16:%.*]] = 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) [[TMP2]], i32 [[TMP9]])
+; CHECK-NEXT:    store i32 [[TMP15]], ptr [[TMP16]], align 4
+; CHECK-NEXT:    br label %[[MAIN_EXIT]]
+; CHECK:       [[MAIN_EXIT]]:
+; CHECK-NEXT:    [[TMP17:%.*]] = load i32, ptr addrspace(2) @f, align 4
+; CHECK-NEXT:    [[TMP18:%.*]] = load i32, ptr addrspace(2) @g, align 4
+; CHECK-NEXT:    [[TMP19:%.*]] = 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) [[TMP2]], i32 [[TMP18]])
+; CHECK-NEXT:    [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4
+; CHECK-NEXT:    [[ADD_I:%.*]] = add i32 [[TMP20]], [[TMP17]]
+; CHECK-NEXT:    store i32 [[ADD_I]], ptr [[TMP19]], align 4
+; CHECK-NEXT:    ret void
+;
+entry:
+  %0 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_i32_1_0t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @.str)
+  store target("dx.RawBuffer", i32, 1, 0) %0, ptr @a, align 4
+  store target("dx.RawBuffer", i32, 1, 0) %0, ptr getelementptr inbounds nuw (i8, ptr @a, i32 4), align 4
+  %1 = 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 @.str.2)
+  store target("dx.RawBuffer", i32, 1, 0) %1, ptr @b, align 4
+  store target("dx.RawBuffer", i32, 1, 0) %1, ptr getelementptr inbounds nuw (i8, ptr @b, i32 4), align 4
+  %2 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_i32_1_0t(i32 4, i32 0, i32 1, i32 0, ptr nonnull @.str.4)
+  store target("dx.RawBuffer", i32, 1, 0) %2, ptr @c, align 4
+  store target("dx.RawBuffer", i32, 1, 0) %2, ptr getelementptr inbounds nuw (i8, ptr @c, i32 4), align 4
+  %d.cb_h.i.i = tail call target("dx.CBuffer", %__cblayout_d) @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_s___cblayout_dst(i32 6, i32 0, i32 1, i32 0, ptr nonnull @d.str)
+  store target("dx.CBuffer", %__cblayout_d) %d.cb_h.i.i, ptr @d.cb, align 4
+  %3 = load i32, ptr addrspace(2) @h, align 4
+  %tobool.not.i = icmp eq i32 %3, 0
+  br i1 %tobool.not.i, label %if.else.i, label %if.then.i
+
+if.then.i:                                        ; preds = %entry
+  %4 = load i32, ptr addrspace(2) @f, align 4
+  %5 = 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) %1, i32 %4)
+  %6 = load i32, ptr %5, align 4
+  %7 = load i32, ptr addrspace(2) @g, align 4
+  %8 = 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) %2, i32 %7)
+  store i32 %6, ptr %8, align 4
+  br label %main.exit
+
+if.else.i:                                        ; preds = %entry
+  %9 = load i32, ptr addrspace(2) @g, align 4
+  %cmp.i = icmp eq i32 %9, 0
+  br i1 %cmp.i, label %if.then2.i, label %if.else6.i
+
+if.then2.i:                                       ; preds = %if.else.i
+  %10 = 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) %1, i32 0)
+  %11 = load i32, ptr %10, align 4
+  %12 = 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) %2, i32 0)
+  store i32 %11, ptr %12, align 4
+  br label %main.exit
+
+if.else6.i:                                       ; preds = %if.else.i
+  %13 = load i32, ptr addrspace(2) @e, align 4
+  %14 = 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) %0, i32 %13)
+  %15 = load i32, ptr %14, align 4
+  %16 = 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) %2, i32 %9)
+  store i32 %15, ptr %16, align 4
+  br label %main.exit
+
+main.exit:                                    ; preds = %if.then.i, %if.then2.i, %if.else6.i
+  %17 = load i32, ptr addrspace(2) @f, align 4
+  %18 = load i32, ptr addrspace(2) @g, align 4
+  %19 = 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) %2, i32 %18)
+  %20 = load i32, ptr %19, align 4
+  %add.i = add i32 %20, %17
+  store i32 %add.i, ptr %19, align 4
+  ret void
+}

>From 8c5a1ed52bc85104ed9bdea96304222f63bf291f Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Thu, 12 Feb 2026 13:47:50 -0800
Subject: [PATCH 2/3] nfc: remove dead code

- this code and hence test cases are now unreachable from code
generation
---
 .../lib/Target/DirectX/DXILResourceAccess.cpp | 122 +-------------
 llvm/test/CodeGen/DirectX/issue-152348.ll     | 158 ------------------
 .../CodeGen/DirectX/phi-node-replacement.ll   |  42 -----
 3 files changed, 1 insertion(+), 321 deletions(-)
 delete mode 100644 llvm/test/CodeGen/DirectX/issue-152348.ll
 delete mode 100644 llvm/test/CodeGen/DirectX/phi-node-replacement.ll

diff --git a/llvm/lib/Target/DirectX/DXILResourceAccess.cpp b/llvm/lib/Target/DirectX/DXILResourceAccess.cpp
index 3d75d7455101f..50b657aab79fb 100644
--- a/llvm/lib/Target/DirectX/DXILResourceAccess.cpp
+++ b/llvm/lib/Target/DirectX/DXILResourceAccess.cpp
@@ -419,112 +419,6 @@ static void createLoadIntrinsic(IntrinsicInst *II, LoadInst *LI,
   llvm_unreachable("Unhandled case in switch");
 }
 
-static SmallVector<Instruction *> collectBlockUseDef(Instruction *Start) {
-  SmallPtrSet<Instruction *, 32> Visited;
-  SmallVector<Instruction *, 32> Worklist;
-  SmallVector<Instruction *> Out;
-  auto *BB = Start->getParent();
-
-  // Seed with direct users in this block.
-  for (User *U : Start->users()) {
-    if (auto *I = dyn_cast<Instruction>(U)) {
-      if (I->getParent() == BB)
-        Worklist.push_back(I);
-    }
-  }
-
-  // BFS over transitive users, constrained to the same block.
-  while (!Worklist.empty()) {
-    Instruction *I = Worklist.pop_back_val();
-    if (!Visited.insert(I).second)
-      continue;
-    Out.push_back(I);
-
-    for (User *U : I->users()) {
-      if (auto *J = dyn_cast<Instruction>(U)) {
-        if (J->getParent() == BB)
-          Worklist.push_back(J);
-      }
-    }
-    for (Use &V : I->operands()) {
-      if (auto *J = dyn_cast<Instruction>(V)) {
-        if (J->getParent() == BB && V != Start)
-          Worklist.push_back(J);
-      }
-    }
-  }
-
-  // Order results in program order.
-  DenseMap<const Instruction *, unsigned> Ord;
-  unsigned Idx = 0;
-  for (Instruction &I : *BB)
-    Ord[&I] = Idx++;
-
-  llvm::sort(Out, [&](Instruction *A, Instruction *B) {
-    return Ord.lookup(A) < Ord.lookup(B);
-  });
-
-  return Out;
-}
-
-static void phiNodeRemapHelper(PHINode *Phi, BasicBlock *BB,
-                               IRBuilder<> &Builder,
-                               SmallVector<Instruction *> &UsesInBlock) {
-
-  ValueToValueMapTy VMap;
-  Value *Val = Phi->getIncomingValueForBlock(BB);
-  VMap[Phi] = Val;
-  Builder.SetInsertPoint(&BB->back());
-  for (Instruction *I : UsesInBlock) {
-    // don't clone over the Phi just remap them
-    if (auto *PhiNested = dyn_cast<PHINode>(I)) {
-      VMap[PhiNested] = PhiNested->getIncomingValueForBlock(BB);
-      continue;
-    }
-    Instruction *Clone = I->clone();
-    RemapInstruction(Clone, VMap,
-                     RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
-    Builder.Insert(Clone);
-    VMap[I] = Clone;
-  }
-}
-
-static void phiNodeReplacement(IntrinsicInst *II,
-                               SmallVectorImpl<Instruction *> &PrevBBDeadInsts,
-                               SetVector<BasicBlock *> &DeadBB) {
-  SmallVector<Instruction *> CurrBBDeadInsts;
-  for (User *U : II->users()) {
-    auto *Phi = dyn_cast<PHINode>(U);
-    if (!Phi)
-      continue;
-
-    IRBuilder<> Builder(Phi);
-    SmallVector<Instruction *> UsesInBlock = collectBlockUseDef(Phi);
-    bool HasReturnUse = isa<ReturnInst>(UsesInBlock.back());
-
-    for (unsigned I = 0, E = Phi->getNumIncomingValues(); I < E; I++) {
-      auto *CurrIncomingBB = Phi->getIncomingBlock(I);
-      phiNodeRemapHelper(Phi, CurrIncomingBB, Builder, UsesInBlock);
-      if (HasReturnUse)
-        PrevBBDeadInsts.push_back(&CurrIncomingBB->back());
-    }
-
-    CurrBBDeadInsts.push_back(Phi);
-
-    for (Instruction *I : UsesInBlock) {
-      CurrBBDeadInsts.push_back(I);
-    }
-    if (HasReturnUse) {
-      BasicBlock *PhiBB = Phi->getParent();
-      DeadBB.insert(PhiBB);
-    }
-  }
-  // Traverse the now-dead instructions in RPO and remove them.
-  for (Instruction *Dead : llvm::reverse(CurrBBDeadInsts))
-    Dead->eraseFromParent();
-  CurrBBDeadInsts.clear();
-}
-
 static void replaceAccess(IntrinsicInst *II, dxil::ResourceTypeInfo &RTI) {
   SmallVector<User *> Worklist;
   for (User *U : II->users())
@@ -560,27 +454,13 @@ static void replaceAccess(IntrinsicInst *II, dxil::ResourceTypeInfo &RTI) {
 
 static bool transformResourcePointers(Function &F, DXILResourceTypeMap &DRTM) {
   SmallVector<std::pair<IntrinsicInst *, dxil::ResourceTypeInfo>> Resources;
-  SetVector<BasicBlock *> DeadBB;
-  SmallVector<Instruction *> PrevBBDeadInsts;
-  for (BasicBlock &BB : make_early_inc_range(F)) {
-    for (Instruction &I : make_early_inc_range(BB))
-      if (auto *II = dyn_cast<IntrinsicInst>(&I))
-        if (II->getIntrinsicID() == Intrinsic::dx_resource_getpointer)
-          phiNodeReplacement(II, PrevBBDeadInsts, DeadBB);
-
+  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) {
           auto *HandleTy = cast<TargetExtType>(II->getArgOperand(0)->getType());
           Resources.emplace_back(II, DRTM[HandleTy]);
         }
-  }
-  for (auto *Dead : PrevBBDeadInsts)
-    Dead->eraseFromParent();
-  PrevBBDeadInsts.clear();
-  for (auto *Dead : DeadBB)
-    Dead->eraseFromParent();
-  DeadBB.clear();
 
   for (auto &[II, RI] : Resources)
     replaceAccess(II, RI);
diff --git a/llvm/test/CodeGen/DirectX/issue-152348.ll b/llvm/test/CodeGen/DirectX/issue-152348.ll
deleted file mode 100644
index aa0179d82b09e..0000000000000
--- a/llvm/test/CodeGen/DirectX/issue-152348.ll
+++ /dev/null
@@ -1,158 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
-; RUN: opt -S -dxil-resource-type -dxil-resource-access -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
-
-; NOTE: The two LLVM IR functions below are simplified versions of this HLSL
-;      RWStructuredBuffer<float16_t> a;
-;      RWStructuredBuffer<float16_t> b;
-;      RWStructuredBuffer<float16_t> c;
-;      cbuffer d {
-;        uint e;
-;        uint f;
-;        uint g;
-;        uint h;
-;      }
-;      [numthreads(6, 8, 1)] void CSMain() {
-;        if (h) {
-;          float16_t i = b[f];
-;          c[g] = i;
-;        } else if(h == g) {
-;          float16_t i = b[g];
-;           c[h] = i;
-;        } else {
-;          float16_t i = a[e];
-;          c[g] = i;
-;        }
-;      }
-
-%__cblayout_d = type <{ i32, i32, i32, i32 }>
-
- at .str = internal unnamed_addr constant [2 x i8] c"a\00", align 1
- at d.cb = local_unnamed_addr global target("dx.CBuffer", target("dx.Layout", %__cblayout_d, 16, 0, 4, 8, 12)) poison
- at e = external hidden local_unnamed_addr addrspace(2) global i32, align 4
- at d.str = internal unnamed_addr constant [2 x i8] c"d\00", align 1
-
-define void @CSMain() local_unnamed_addr {
-; CHECK-LABEL: define void @CSMain() local_unnamed_addr {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[CALLRAWBUFFERBINDING:%.*]] = tail call target("dx.CBuffer", target("dx.Layout", [[__CBLAYOUT_D:%.*]], 16, 0, 4, 8, 12)) @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_ds_16_0_4_8_12tt(i32 3, i32 0, i32 1, i32 0, ptr nonnull @d.str)
-; CHECK-NEXT:    store target("dx.CBuffer", target("dx.Layout", [[__CBLAYOUT_D]], 16, 0, 4, 8, 12)) [[CALLRAWBUFFERBINDING]], ptr @d.cb, align 4
-; CHECK-NEXT:    [[LOADE:%.*]] = load i32, ptr addrspace(2) @e, align 4
-; CHECK-NEXT:    [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[LOADE]], 0
-; CHECK-NEXT:    br i1 [[TOBOOL_NOT_I]], label %[[IF_ELSE_I:.*]], label %[[IF_THEN_I:.*]]
-; CHECK:       [[IF_THEN_I]]:
-; CHECK-NEXT:    [[IFSTMTCALLRAWBUFFERBINDING:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 1, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT:    [[TMP0:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 2, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT:    [[TMP1:%.*]] = call { half, i1 } @llvm.dx.resource.load.rawbuffer.f16.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) [[IFSTMTCALLRAWBUFFERBINDING]], i32 [[LOADE]], i32 0)
-; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { half, i1 } [[TMP1]], 0
-; CHECK-NEXT:    call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_f16_1_0t.f16(target("dx.RawBuffer", half, 1, 0) [[TMP0]], i32 [[LOADE]], i32 0, half [[TMP2]])
-; CHECK-NEXT:    br label %[[_Z6CSMAINV_EXIT:.*]]
-; CHECK:       [[IF_ELSE_I]]:
-; CHECK-NEXT:    [[CALL2NDRAWBUFFERBINDING:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT:    [[TMP3:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 2, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT:    [[TMP4:%.*]] = call { half, i1 } @llvm.dx.resource.load.rawbuffer.f16.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) [[CALL2NDRAWBUFFERBINDING]], i32 [[LOADE]], i32 0)
-; CHECK-NEXT:    [[TMP5:%.*]] = extractvalue { half, i1 } [[TMP4]], 0
-; CHECK-NEXT:    call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_f16_1_0t.f16(target("dx.RawBuffer", half, 1, 0) [[TMP3]], i32 [[LOADE]], i32 0, half [[TMP5]])
-; CHECK-NEXT:    br label %[[_Z6CSMAINV_EXIT]]
-; CHECK:       [[_Z6CSMAINV_EXIT]]:
-; CHECK-NEXT:    ret void
-;
-entry:
-  %callCBufferBinding = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_d, 16, 0, 4, 8, 12)) @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_ds_16_0_4_8_12tt(i32 3, i32 0, i32 1, i32 0, ptr nonnull @d.str)
-  store target("dx.CBuffer", target("dx.Layout", %__cblayout_d, 16, 0, 4, 8, 12)) %callCBufferBinding, ptr @d.cb, align 4
-  %loadE = load i32, ptr addrspace(2) @e, align 4
-  %tobool.not.i = icmp eq i32 %loadE, 0
-  br i1 %tobool.not.i, label %if.else.i, label %if.then.i
-
-if.then.i:                                        ; preds = %entry
-  %ifStmtcallRawBufferBinding = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 1, i32 0, i32 1, i32 0, ptr nonnull @.str)
-  %ifStmtCallResourceGEP = tail call noundef nonnull align 2 dereferenceable(2) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) %ifStmtcallRawBufferBinding, i32 %loadE)
-  br label %_Z6CSMainv.exit
-
-if.else.i:                                        ; preds = %entry
-  %call2ndRawBufferBinding = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @.str)
-  %elseStmtCallResourceGEP = tail call noundef nonnull align 2 dereferenceable(2) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) %call2ndRawBufferBinding, i32 %loadE)
-  br label %_Z6CSMainv.exit
-
-_Z6CSMainv.exit:                                  ; preds = %if.else.i, %if.then.i
-  %.sink1 = phi ptr [ %ifStmtCallResourceGEP, %if.then.i ], [ %elseStmtCallResourceGEP, %if.else.i ]
-  %call3rdRawBufferBinding = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 2, i32 0, i32 1, i32 0, ptr nonnull @.str)
-  %sinkCallResourceGEP = tail call noundef nonnull align 2 dereferenceable(2) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) %call3rdRawBufferBinding, i32 %loadE)
-  %loadSink = load half, ptr %.sink1, align 2
-  store half %loadSink, ptr %sinkCallResourceGEP, align 2
-  ret void
-}
-
-define void @Main() local_unnamed_addr  {
-; CHECK-LABEL: define void @Main() local_unnamed_addr {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[CALLRAWBUFFERBINDING1:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT:    [[CALLRAWBUFFERBINDING0:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 1, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT:    [[CALLRAWBUFFERBINDING:%.*]] = tail call target("dx.CBuffer", target("dx.Layout", [[__CBLAYOUT_D:%.*]], 16, 0, 4, 8, 12)) @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_ds_16_0_4_8_12tt(i32 3, i32 0, i32 1, i32 0, ptr nonnull @d.str)
-; CHECK-NEXT:    store target("dx.CBuffer", target("dx.Layout", [[__CBLAYOUT_D]], 16, 0, 4, 8, 12)) [[CALLRAWBUFFERBINDING]], ptr @d.cb, align 4
-; CHECK-NEXT:    [[LOADE:%.*]] = load i32, ptr addrspace(2) @e, align 4
-; CHECK-NEXT:    [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[LOADE]], 0
-; CHECK-NEXT:    br i1 [[TOBOOL_NOT_I]], label %[[IF_ELSE_I:.*]], label %[[IF_THEN_I:.*]]
-; CHECK:       [[IF_THEN_I]]:
-; CHECK-NEXT:    [[IFSTMTLOADE:%.*]] = load i32, ptr addrspace(2) @e, align 4
-; CHECK-NEXT:    [[TMP0:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 2, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT:    [[TMP1:%.*]] = call { half, i1 } @llvm.dx.resource.load.rawbuffer.f16.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) [[CALLRAWBUFFERBINDING0]], i32 [[LOADE]], i32 0)
-; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { half, i1 } [[TMP1]], 0
-; CHECK-NEXT:    call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_f16_1_0t.f16(target("dx.RawBuffer", half, 1, 0) [[TMP0]], i32 [[IFSTMTLOADE]], i32 0, half [[TMP2]])
-; CHECK-NEXT:    br label %[[_Z6MAINV_EXIT:.*]]
-; CHECK:       [[IF_ELSE_I]]:
-; CHECK-NEXT:    [[ELSESTMTLOADE:%.*]] = load i32, ptr addrspace(2) @e, align 4
-; CHECK-NEXT:    [[CMP_I:%.*]] = icmp eq i32 [[ELSESTMTLOADE]], 0
-; CHECK-NEXT:    br i1 [[CMP_I]], label %[[IF_THEN2_I:.*]], label %[[IF_ELSE6_I:.*]]
-; CHECK:       [[IF_THEN2_I]]:
-; CHECK-NEXT:    [[TMP3:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 2, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT:    [[TMP4:%.*]] = call { half, i1 } @llvm.dx.resource.load.rawbuffer.f16.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) [[CALLRAWBUFFERBINDING0]], i32 0, i32 0)
-; CHECK-NEXT:    [[TMP5:%.*]] = extractvalue { half, i1 } [[TMP4]], 0
-; CHECK-NEXT:    call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_f16_1_0t.f16(target("dx.RawBuffer", half, 1, 0) [[TMP3]], i32 0, i32 0, half [[TMP5]])
-; CHECK-NEXT:    br label %[[_Z6MAINV_EXIT]]
-; CHECK:       [[IF_ELSE6_I]]:
-; CHECK-NEXT:    [[ELSESTMTLOADE2:%.*]] = load i32, ptr addrspace(2) @e, align 4
-; CHECK-NEXT:    [[TMP6:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 2, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT:    [[TMP7:%.*]] = call { half, i1 } @llvm.dx.resource.load.rawbuffer.f16.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) [[CALLRAWBUFFERBINDING1]], i32 [[ELSESTMTLOADE2]], i32 0)
-; CHECK-NEXT:    [[TMP8:%.*]] = extractvalue { half, i1 } [[TMP7]], 0
-; CHECK-NEXT:    call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_f16_1_0t.f16(target("dx.RawBuffer", half, 1, 0) [[TMP6]], i32 [[ELSESTMTLOADE]], i32 0, half [[TMP8]])
-; CHECK-NEXT:    br label %[[_Z6MAINV_EXIT]]
-; CHECK:       [[_Z6MAINV_EXIT]]:
-; CHECK-NEXT:    ret void
-;
-entry:
-  %callRawBufferBinding1 = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @.str)
-  %callRawBufferBinding0 = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 1, i32 0, i32 1, i32 0, ptr nonnull @.str)
-  %callCBufferBinding = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_d, 16, 0, 4, 8, 12)) @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_ds_16_0_4_8_12tt(i32 3, i32 0, i32 1, i32 0, ptr nonnull @d.str)
-  store target("dx.CBuffer", target("dx.Layout", %__cblayout_d, 16, 0, 4, 8, 12)) %callCBufferBinding, ptr @d.cb, align 4
-  %loadE = load i32, ptr addrspace(2) @e, align 4
-  %tobool.not.i = icmp eq i32 %loadE, 0
-  br i1 %tobool.not.i, label %if.else.i, label %if.then.i
-
-if.then.i:                                        ; preds = %entry
-  %ifStmtCallResourceGEP = tail call noundef nonnull align 2 dereferenceable(2) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) %callRawBufferBinding0, i32 %loadE)
-  %ifStmtLoadE = load i32, ptr addrspace(2) @e, align 4
-  br label %_Z6Mainv.exit
-
-if.else.i:                                        ; preds = %entry
-  %elseStmtLoadE = load i32, ptr addrspace(2) @e, align 4
-  %cmp.i = icmp eq i32 %elseStmtLoadE, 0
-  br i1 %cmp.i, label %if.then2.i, label %if.else6.i
-
-if.then2.i:                                       ; preds = %if.else.i
-  %elseifStmtCallResourceGEP = tail call noundef nonnull align 2 dereferenceable(2) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) %callRawBufferBinding0, i32 0)
-  br label %_Z6Mainv.exit
-
-if.else6.i:                                       ; preds = %if.else.i
-  %elseStmtLoadE2 = load i32, ptr addrspace(2) @e, align 4
-  %elseStmtCallResourceGEP = tail call noundef nonnull align 2 dereferenceable(2) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) %callRawBufferBinding1, i32 %elseStmtLoadE2)
-  br label %_Z6Mainv.exit
-
-_Z6Mainv.exit:                                    ; preds = %if.else6.i, %if.then2.i, %if.then.i
-  %.sink2 = phi i32 [ %ifStmtLoadE, %if.then.i ], [ 0, %if.then2.i ], [ %elseStmtLoadE, %if.else6.i ]
-  %.sink.in = phi ptr [ %ifStmtCallResourceGEP, %if.then.i ], [ %elseifStmtCallResourceGEP, %if.then2.i ], [ %elseStmtCallResourceGEP, %if.else6.i ]
-  %callRawBufferBindingSink = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 2, i32 0, i32 1, i32 0, ptr nonnull @.str)
-  %.sink = load half, ptr %.sink.in, align 2
-  %i11 = tail call noundef nonnull align 2 dereferenceable(2) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) %callRawBufferBindingSink, i32 %.sink2)
-  store half %.sink, ptr %i11, align 2
-  ret void
-}
diff --git a/llvm/test/CodeGen/DirectX/phi-node-replacement.ll b/llvm/test/CodeGen/DirectX/phi-node-replacement.ll
deleted file mode 100644
index 6aef126cb5ecd..0000000000000
--- a/llvm/test/CodeGen/DirectX/phi-node-replacement.ll
+++ /dev/null
@@ -1,42 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
-; RUN: opt -S -dxil-resource-type -dxil-resource-access -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
-
-%"$Globals" = type { i32 }
- at CBV = external constant %"$Globals"
- at .str = internal unnamed_addr constant [2 x i8] c"a\00", align 1
-
-define half @CSMain() local_unnamed_addr {
-; CHECK-LABEL: define half @CSMain() local_unnamed_addr {
-; CHECK-NEXT:    [[LOADGLOBAL:%.*]] = load i32, ptr @CBV, align 4
-; CHECK-NEXT:    [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[LOADGLOBAL]], 0
-; CHECK-NEXT:    br i1 [[TOBOOL_NOT_I]], label %[[IF_ELSE_I:.*]], label %[[IF_THEN_I:.*]]
-; CHECK:       [[IF_THEN_I]]:
-; CHECK-NEXT:    [[IFSTMTCALLRAWBUFFERBINDING:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 1, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT:    [[TMP1:%.*]] = call { half, i1 } @llvm.dx.resource.load.rawbuffer.f16.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) [[IFSTMTCALLRAWBUFFERBINDING]], i32 [[LOADGLOBAL]], i32 0)
-; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { half, i1 } [[TMP1]], 0
-; CHECK-NEXT:    ret half [[TMP2]]
-; CHECK:       [[IF_ELSE_I]]:
-; CHECK-NEXT:    [[CALL2NDRAWBUFFERBINDING:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT:    [[TMP3:%.*]] = call { half, i1 } @llvm.dx.resource.load.rawbuffer.f16.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) [[CALL2NDRAWBUFFERBINDING]], i32 [[LOADGLOBAL]], i32 0)
-; CHECK-NEXT:    [[TMP4:%.*]] = extractvalue { half, i1 } [[TMP3]], 0
-; CHECK-NEXT:    ret half [[TMP4]]
-;
-  %loadGlobal = load i32, ptr @CBV, align 4
-  %tobool.not.i = icmp eq i32 %loadGlobal, 0
-  br i1 %tobool.not.i, label %if.else.i, label %if.then.i
-
-  if.then.i:                                        ; preds = %entry
-  %ifStmtcallRawBufferBinding = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 1, i32 0, i32 1, i32 0, ptr nonnull @.str)
-  %ifStmtCallResourceGEP = tail call noundef nonnull align 2 dereferenceable(2) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) %ifStmtcallRawBufferBinding, i32 %loadGlobal)
-  br label %_Z6CSMainv.exit
-
-  if.else.i:                                        ; preds = %entry
-  %call2ndRawBufferBinding = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @.str)
-  %elseStmtCallResourceGEP = tail call noundef nonnull align 2 dereferenceable(2) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) %call2ndRawBufferBinding, i32 %loadGlobal)
-  br label %_Z6CSMainv.exit
-
-  _Z6CSMainv.exit:                                  ; preds = %if.else.i, %if.then.i
-  %.sink1 = phi ptr [ %ifStmtCallResourceGEP, %if.then.i ], [ %elseStmtCallResourceGEP, %if.else.i ]
-  %loadSink = load half, ptr %.sink1, align 2
-  ret half %loadSink
-}

>From 9285ccdd9bd9333a9bf20fc140dd7cc60952b2d6 Mon Sep 17 00:00:00 2001
From: Finn Plummer <mail at inbelic.dev>
Date: Thu, 19 Feb 2026 10:55:30 -0800
Subject: [PATCH 3/3] nfc: specify instnamer to test run lines

---
 llvm/test/Transforms/GVN/no-sink-dxgetpointer.ll                | 2 +-
 .../test/Transforms/SimplifyCFG/DirectX/no-sink-dxgetpointer.ll | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/test/Transforms/GVN/no-sink-dxgetpointer.ll b/llvm/test/Transforms/GVN/no-sink-dxgetpointer.ll
index 4537d5f1abc88..b1af3f6bd0846 100644
--- a/llvm/test/Transforms/GVN/no-sink-dxgetpointer.ll
+++ b/llvm/test/Transforms/GVN/no-sink-dxgetpointer.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
-; RUN: opt -passes=gvn -S %s | FileCheck %s
+; RUN: opt -passes=gvn -passes=instnamer -S %s | FileCheck %s
 
 ; This test ensures that given dx.resource.getpointer is marked convergent, the
 ; GVN pass is prevented from sinking these intrinsics.
diff --git a/llvm/test/Transforms/SimplifyCFG/DirectX/no-sink-dxgetpointer.ll b/llvm/test/Transforms/SimplifyCFG/DirectX/no-sink-dxgetpointer.ll
index 76ab7bf18f3e2..4cc8a7e7f5012 100644
--- a/llvm/test/Transforms/SimplifyCFG/DirectX/no-sink-dxgetpointer.ll
+++ b/llvm/test/Transforms/SimplifyCFG/DirectX/no-sink-dxgetpointer.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
-; RUN: opt -passes=simplifycfg -S %s | FileCheck %s
+; RUN: opt -passes=simplifycfg -passes=instnamer -S %s | FileCheck %s
 
 ; This test ensures that given dx.resource.getpointer is marked convergent, the
 ; SimplifyCFG pass will be prevented from moving these intrinsics into the



More information about the llvm-commits mailing list