[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