| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 |
| ; RUN: opt -passes=gvn,instnamer -S %s | FileCheck %s |
| |
| ; This test ensures that given spv.resource.getpointer is marked convergent, |
| ; the GVN pass is prevented from sinking these intrinsics out of branches which |
| ; would create phi nodes on the returned ptr. |
| ; |
| ; The CHECK lines below match the input IR exactly, so this test verifies that |
| ; the pass makes no changes to the IR. |
| |
| %"class.hlsl::RWBuffer" = type { target("spirv.Image", i32, 5, 2, 0, 0, 2, 1) } |
| %"class.hlsl::RWStructuredBuffer" = type { target("spirv.VulkanBuffer", [0 x i32], 12, 1), target("spirv.VulkanBuffer", [0 x i32], 12, 1) } |
| %__cblayout_c = type <{ i32 }> |
| |
| @In = internal global %"class.hlsl::RWBuffer" poison, align 4 |
| @.str = private unnamed_addr constant [3 x i8] c"In\00", align 1 |
| @Out0 = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4 |
| @.str.2 = private unnamed_addr constant [5 x i8] c"Out0\00", align 1 |
| @Out1 = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4 |
| @.str.4 = private unnamed_addr constant [5 x i8] c"Out1\00", align 1 |
| @c.cb = local_unnamed_addr global target("spirv.VulkanBuffer", %__cblayout_c, 2, 0) poison |
| @cond = external hidden local_unnamed_addr addrspace(2) global i32, align 4 |
| @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: [[I:%.*]] = tail call target("spirv.Image", i32, 5, 2, 0, 0, 2, 1) @llvm.spv.resource.handlefrombinding.tspirv.Image_i32_5_2_0_0_2_1t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @.str) |
| ; CHECK-NEXT: store target("spirv.Image", i32, 5, 2, 0, 0, 2, 1) [[I]], ptr @In, align 4 |
| ; CHECK-NEXT: [[I1:%.*]] = tail call target("spirv.VulkanBuffer", [0 x i32], 12, 1) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_a0i32_12_1t(i32 0, i32 1, i32 1, i32 0, ptr nonnull @.str.2) |
| ; CHECK-NEXT: store target("spirv.VulkanBuffer", [0 x i32], 12, 1) [[I1]], ptr @Out0, align 4 |
| ; CHECK-NEXT: store target("spirv.VulkanBuffer", [0 x i32], 12, 1) [[I1]], ptr getelementptr inbounds nuw (i8, ptr @Out0, i32 8), align 4 |
| ; CHECK-NEXT: [[I2:%.*]] = tail call target("spirv.VulkanBuffer", [0 x i32], 12, 1) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_a0i32_12_1t(i32 0, i32 2, i32 1, i32 0, ptr nonnull @.str.4) |
| ; CHECK-NEXT: store target("spirv.VulkanBuffer", [0 x i32], 12, 1) [[I2]], ptr @Out1, align 4 |
| ; CHECK-NEXT: store target("spirv.VulkanBuffer", [0 x i32], 12, 1) [[I2]], ptr getelementptr inbounds nuw (i8, ptr @Out1, i32 8), align 4 |
| ; CHECK-NEXT: [[C_CB_H_I_I:%.*]] = tail call target("spirv.VulkanBuffer", [[__CBLAYOUT_C:%.*]], 2, 0) @llvm.spv.resource.handlefromimplicitbinding.tspirv.VulkanBuffer_s___cblayout_cs_2_0t(i32 4, i32 0, i32 1, i32 0, ptr nonnull @c.str) |
| ; CHECK-NEXT: store target("spirv.VulkanBuffer", [[__CBLAYOUT_C]], 2, 0) [[C_CB_H_I_I]], ptr @c.cb, align 8 |
| ; CHECK-NEXT: [[I3:%.*]] = tail call i32 @llvm.spv.flattened.thread.id.in.group() |
| ; CHECK-NEXT: [[I4:%.*]] = load i32, ptr addrspace(2) @cond, align 4 |
| ; CHECK-NEXT: [[LOADEDV_I:%.*]] = trunc nuw i32 [[I4]] to i1 |
| ; CHECK-NEXT: br i1 [[LOADEDV_I]], label %[[IF_THEN_I:.*]], label %[[IF_ELSE_I:.*]] |
| ; CHECK: [[IF_THEN_I]]: |
| ; CHECK-NEXT: [[I5:%.*]] = tail call noundef nonnull align 4 dereferenceable(4) ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_i32_5_2_0_0_2_1t.i32(target("spirv.Image", i32, 5, 2, 0, 0, 2, 1) [[I]], i32 [[I3]]) |
| ; CHECK-NEXT: [[I6:%.*]] = load i32, ptr [[I5]], align 4 |
| ; CHECK-NEXT: [[HLSL_WAVE_ACTIVE_SUM_I:%.*]] = tail call i32 @llvm.spv.wave.reduce.sum.i32(i32 [[I6]]) |
| ; CHECK-NEXT: [[I7:%.*]] = tail call noundef nonnull align 4 dereferenceable(4) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0i32_12_1t.i32(target("spirv.VulkanBuffer", [0 x i32], 12, 1) [[I1]], i32 [[I3]]) |
| ; CHECK-NEXT: store i32 [[HLSL_WAVE_ACTIVE_SUM_I]], ptr addrspace(11) [[I7]], align 4 |
| ; CHECK-NEXT: br label %[[MAIN_EXIT:.*]] |
| ; CHECK: [[IF_ELSE_I]]: |
| ; CHECK-NEXT: [[I8:%.*]] = tail call noundef nonnull align 4 dereferenceable(4) ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_i32_5_2_0_0_2_1t.i32(target("spirv.Image", i32, 5, 2, 0, 0, 2, 1) [[I]], i32 [[I3]]) |
| ; CHECK-NEXT: [[I9:%.*]] = load i32, ptr [[I8]], align 4 |
| ; CHECK-NEXT: [[I10:%.*]] = tail call noundef nonnull align 4 dereferenceable(4) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0i32_12_1t.i32(target("spirv.VulkanBuffer", [0 x i32], 12, 1) [[I1]], i32 0) |
| ; CHECK-NEXT: store i32 [[I9]], ptr addrspace(11) [[I10]], align 4 |
| ; CHECK-NEXT: br label %[[MAIN_EXIT]] |
| ; CHECK: [[MAIN_EXIT]]: |
| ; CHECK-NEXT: [[I11:%.*]] = tail call noundef nonnull align 4 dereferenceable(4) ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_i32_5_2_0_0_2_1t.i32(target("spirv.Image", i32, 5, 2, 0, 0, 2, 1) [[I]], i32 [[I3]]) |
| ; CHECK-NEXT: [[I12:%.*]] = load i32, ptr [[I11]], align 4 |
| ; CHECK-NEXT: [[HLSL_WAVE_ACTIVE_SUM5_I:%.*]] = tail call i32 @llvm.spv.wave.reduce.sum.i32(i32 [[I12]]) |
| ; CHECK-NEXT: [[I13:%.*]] = tail call noundef nonnull align 4 dereferenceable(4) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0i32_12_1t.i32(target("spirv.VulkanBuffer", [0 x i32], 12, 1) [[I1]], i32 [[I3]]) |
| ; CHECK-NEXT: store i32 [[HLSL_WAVE_ACTIVE_SUM5_I]], ptr addrspace(11) [[I13]], align 4 |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| %0 = tail call target("spirv.Image", i32, 5, 2, 0, 0, 2, 1) @llvm.spv.resource.handlefrombinding.tspirv.Image_i32_5_2_0_0_2_1t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @.str) |
| store target("spirv.Image", i32, 5, 2, 0, 0, 2, 1) %0, ptr @In, align 4 |
| %1 = tail call target("spirv.VulkanBuffer", [0 x i32], 12, 1) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_a0i32_12_1t(i32 0, i32 1, i32 1, i32 0, ptr nonnull @.str.2) |
| store target("spirv.VulkanBuffer", [0 x i32], 12, 1) %1, ptr @Out0, align 4 |
| store target("spirv.VulkanBuffer", [0 x i32], 12, 1) %1, ptr getelementptr inbounds nuw (i8, ptr @Out0, i32 8), align 4 |
| %2 = tail call target("spirv.VulkanBuffer", [0 x i32], 12, 1) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_a0i32_12_1t(i32 0, i32 2, i32 1, i32 0, ptr nonnull @.str.4) |
| store target("spirv.VulkanBuffer", [0 x i32], 12, 1) %2, ptr @Out1, align 4 |
| store target("spirv.VulkanBuffer", [0 x i32], 12, 1) %2, ptr getelementptr inbounds nuw (i8, ptr @Out1, i32 8), align 4 |
| %c.cb_h.i.i = tail call target("spirv.VulkanBuffer", %__cblayout_c, 2, 0) @llvm.spv.resource.handlefromimplicitbinding.tspirv.VulkanBuffer_s___cblayout_cs_2_0t(i32 4, i32 0, i32 1, i32 0, ptr nonnull @c.str) |
| store target("spirv.VulkanBuffer", %__cblayout_c, 2, 0) %c.cb_h.i.i, ptr @c.cb, align 8 |
| %3 = tail call i32 @llvm.spv.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.spv.resource.getpointer.p0.tspirv.Image_i32_5_2_0_0_2_1t.i32(target("spirv.Image", i32, 5, 2, 0, 0, 2, 1) %0, i32 %3) |
| %6 = load i32, ptr %5, align 4 |
| %hlsl.wave.active.sum.i = tail call i32 @llvm.spv.wave.reduce.sum.i32(i32 %6) |
| %7 = tail call noundef nonnull align 4 dereferenceable(4) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0i32_12_1t.i32(target("spirv.VulkanBuffer", [0 x i32], 12, 1) %1, i32 %3) |
| store i32 %hlsl.wave.active.sum.i, ptr addrspace(11) %7, align 4 |
| br label %main.exit |
| |
| if.else.i: ; preds = %entry |
| %8 = tail call noundef nonnull align 4 dereferenceable(4) ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_i32_5_2_0_0_2_1t.i32(target("spirv.Image", i32, 5, 2, 0, 0, 2, 1) %0, i32 %3) |
| %9 = load i32, ptr %8, align 4 |
| %10 = tail call noundef nonnull align 4 dereferenceable(4) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0i32_12_1t.i32(target("spirv.VulkanBuffer", [0 x i32], 12, 1) %1, i32 0) |
| store i32 %9, ptr addrspace(11) %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.spv.resource.getpointer.p0.tspirv.Image_i32_5_2_0_0_2_1t.i32(target("spirv.Image", i32, 5, 2, 0, 0, 2, 1) %0, i32 %3) |
| %12 = load i32, ptr %11, align 4 |
| %hlsl.wave.active.sum5.i = tail call i32 @llvm.spv.wave.reduce.sum.i32(i32 %12) |
| %13 = tail call noundef nonnull align 4 dereferenceable(4) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0i32_12_1t.i32(target("spirv.VulkanBuffer", [0 x i32], 12, 1) %1, i32 %3) |
| store i32 %hlsl.wave.active.sum5.i, ptr addrspace(11) %13, align 4 |
| ret void |
| } |