| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 |
| ; RUN: opt -passes=simplifycfg,instnamer -S %s | FileCheck %s |
| |
| ; This test ensures that given spv.resource.getpointer is marked convergent, |
| ; the SimplifyCFG pass will be 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::RWStructuredBuffer" = type { target("spirv.VulkanBuffer", [0 x i32], 12, 1), target("spirv.VulkanBuffer", [0 x i32], 12, 1) } |
| %__cblayout_d = type <{ i32, i32, i32, i32 }> |
| |
| @a = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4 |
| @.str = private unnamed_addr constant [2 x i8] c"a\00", align 1 |
| @b = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4 |
| @.str.2 = private unnamed_addr constant [2 x i8] c"b\00", align 1 |
| @c = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4 |
| @.str.4 = private unnamed_addr constant [2 x i8] c"c\00", align 1 |
| @d.cb = local_unnamed_addr global target("spirv.VulkanBuffer", %__cblayout_d, 2, 0) poison |
| @e = external hidden local_unnamed_addr addrspace(2) global i32, align 4 |
| @f = external hidden local_unnamed_addr addrspace(2) global i32, align 4 |
| @g = external hidden local_unnamed_addr addrspace(2) global i32, align 4 |
| @h = external hidden local_unnamed_addr addrspace(2) global i32, align 4 |
| @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: [[I:%.*]] = tail call target("spirv.VulkanBuffer", [0 x i32], 12, 1) @llvm.spv.resource.handlefromimplicitbinding.tspirv.VulkanBuffer_a0i32_12_1t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @.str) |
| ; CHECK-NEXT: store target("spirv.VulkanBuffer", [0 x i32], 12, 1) [[I]], ptr @a, align 4 |
| ; CHECK-NEXT: store target("spirv.VulkanBuffer", [0 x i32], 12, 1) [[I]], ptr getelementptr inbounds nuw (i8, ptr @a, i32 8), align 4 |
| ; CHECK-NEXT: [[I1:%.*]] = tail call target("spirv.VulkanBuffer", [0 x i32], 12, 1) @llvm.spv.resource.handlefromimplicitbinding.tspirv.VulkanBuffer_a0i32_12_1t(i32 2, i32 0, i32 1, i32 0, ptr nonnull @.str.2) |
| ; CHECK-NEXT: store target("spirv.VulkanBuffer", [0 x i32], 12, 1) [[I1]], ptr @b, align 4 |
| ; CHECK-NEXT: store target("spirv.VulkanBuffer", [0 x i32], 12, 1) [[I1]], ptr getelementptr inbounds nuw (i8, ptr @b, i32 8), align 4 |
| ; CHECK-NEXT: [[I2:%.*]] = tail call target("spirv.VulkanBuffer", [0 x i32], 12, 1) @llvm.spv.resource.handlefromimplicitbinding.tspirv.VulkanBuffer_a0i32_12_1t(i32 4, i32 0, i32 1, i32 0, ptr nonnull @.str.4) |
| ; CHECK-NEXT: store target("spirv.VulkanBuffer", [0 x i32], 12, 1) [[I2]], ptr @c, align 4 |
| ; CHECK-NEXT: store target("spirv.VulkanBuffer", [0 x i32], 12, 1) [[I2]], ptr getelementptr inbounds nuw (i8, ptr @c, i32 8), align 4 |
| ; CHECK-NEXT: [[D_CB_H_I_I:%.*]] = tail call target("spirv.VulkanBuffer", [[__CBLAYOUT_D:%.*]], 2, 0) @llvm.spv.resource.handlefromimplicitbinding.tspirv.VulkanBuffer_s___cblayout_ds_2_0t(i32 6, i32 0, i32 1, i32 0, ptr nonnull @d.str) |
| ; CHECK-NEXT: store target("spirv.VulkanBuffer", [[__CBLAYOUT_D]], 2, 0) [[D_CB_H_I_I]], ptr @d.cb, align 8 |
| ; CHECK-NEXT: [[I3:%.*]] = load i32, ptr addrspace(2) @h, align 4 |
| ; CHECK-NEXT: [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[I3]], 0 |
| ; CHECK-NEXT: br i1 [[TOBOOL_NOT_I]], label %[[IF_ELSE_I:.*]], label %[[IF_THEN_I:.*]] |
| ; CHECK: [[IF_THEN_I]]: |
| ; CHECK-NEXT: [[I4:%.*]] = load i32, ptr addrspace(2) @f, align 4 |
| ; CHECK-NEXT: [[I5:%.*]] = 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 [[I4]]) |
| ; CHECK-NEXT: [[I6:%.*]] = load i32, ptr addrspace(11) [[I5]], align 4 |
| ; CHECK-NEXT: [[I7:%.*]] = load i32, ptr addrspace(2) @g, align 4 |
| ; CHECK-NEXT: [[I8:%.*]] = 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) [[I2]], i32 [[I7]]) |
| ; CHECK-NEXT: store i32 [[I6]], ptr addrspace(11) [[I8]], align 4 |
| ; CHECK-NEXT: br label %[[MAIN_EXIT:.*]] |
| ; CHECK: [[IF_ELSE_I]]: |
| ; CHECK-NEXT: [[I9:%.*]] = load i32, ptr addrspace(2) @g, align 4 |
| ; CHECK-NEXT: [[CMP_I:%.*]] = icmp eq i32 [[I9]], 0 |
| ; CHECK-NEXT: br i1 [[CMP_I]], label %[[IF_THEN2_I:.*]], label %[[IF_ELSE6_I:.*]] |
| ; CHECK: [[IF_THEN2_I]]: |
| ; 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: [[I11:%.*]] = load i32, ptr addrspace(11) [[I10]], align 4 |
| ; CHECK-NEXT: [[I12:%.*]] = 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) [[I2]], i32 0) |
| ; CHECK-NEXT: store i32 [[I11]], ptr addrspace(11) [[I12]], align 4 |
| ; CHECK-NEXT: br label %[[MAIN_EXIT]] |
| ; CHECK: [[IF_ELSE6_I]]: |
| ; CHECK-NEXT: [[I13:%.*]] = load i32, ptr addrspace(2) @e, align 4 |
| ; CHECK-NEXT: [[I14:%.*]] = 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) [[I]], i32 [[I13]]) |
| ; CHECK-NEXT: [[I15:%.*]] = load i32, ptr addrspace(11) [[I14]], align 4 |
| ; CHECK-NEXT: [[I16:%.*]] = 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) [[I2]], i32 [[I9]]) |
| ; CHECK-NEXT: store i32 [[I15]], ptr addrspace(11) [[I16]], align 4 |
| ; CHECK-NEXT: br label %[[MAIN_EXIT]] |
| ; CHECK: [[MAIN_EXIT]]: |
| ; CHECK-NEXT: [[I17:%.*]] = load i32, ptr addrspace(2) @f, align 4 |
| ; CHECK-NEXT: [[I18:%.*]] = load i32, ptr addrspace(2) @g, align 4 |
| ; CHECK-NEXT: [[I19:%.*]] = 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) [[I2]], i32 [[I18]]) |
| ; CHECK-NEXT: [[I20:%.*]] = load i32, ptr addrspace(11) [[I19]], align 4 |
| ; CHECK-NEXT: [[ADD_I:%.*]] = add i32 [[I20]], [[I17]] |
| ; CHECK-NEXT: store i32 [[ADD_I]], ptr addrspace(11) [[I19]], align 4 |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| %0 = tail call target("spirv.VulkanBuffer", [0 x i32], 12, 1) @llvm.spv.resource.handlefromimplicitbinding.tspirv.VulkanBuffer_a0i32_12_1t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @.str) |
| store target("spirv.VulkanBuffer", [0 x i32], 12, 1) %0, ptr @a, align 4 |
| store target("spirv.VulkanBuffer", [0 x i32], 12, 1) %0, ptr getelementptr inbounds nuw (i8, ptr @a, i32 8), align 4 |
| %1 = tail call target("spirv.VulkanBuffer", [0 x i32], 12, 1) @llvm.spv.resource.handlefromimplicitbinding.tspirv.VulkanBuffer_a0i32_12_1t(i32 2, i32 0, i32 1, i32 0, ptr nonnull @.str.2) |
| store target("spirv.VulkanBuffer", [0 x i32], 12, 1) %1, ptr @b, align 4 |
| store target("spirv.VulkanBuffer", [0 x i32], 12, 1) %1, ptr getelementptr inbounds nuw (i8, ptr @b, i32 8), align 4 |
| %2 = tail call target("spirv.VulkanBuffer", [0 x i32], 12, 1) @llvm.spv.resource.handlefromimplicitbinding.tspirv.VulkanBuffer_a0i32_12_1t(i32 4, i32 0, i32 1, i32 0, ptr nonnull @.str.4) |
| store target("spirv.VulkanBuffer", [0 x i32], 12, 1) %2, ptr @c, align 4 |
| store target("spirv.VulkanBuffer", [0 x i32], 12, 1) %2, ptr getelementptr inbounds nuw (i8, ptr @c, i32 8), align 4 |
| %d.cb_h.i.i = tail call target("spirv.VulkanBuffer", %__cblayout_d, 2, 0) @llvm.spv.resource.handlefromimplicitbinding.tspirv.VulkanBuffer_s___cblayout_ds_2_0t(i32 6, i32 0, i32 1, i32 0, ptr nonnull @d.str) |
| store target("spirv.VulkanBuffer", %__cblayout_d, 2, 0) %d.cb_h.i.i, ptr @d.cb, align 8 |
| %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 addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0i32_12_1t.i32(target("spirv.VulkanBuffer", [0 x i32], 12, 1) %1, i32 %4) |
| %6 = load i32, ptr addrspace(11) %5, align 4 |
| %7 = load i32, ptr addrspace(2) @g, align 4 |
| %8 = 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) %2, i32 %7) |
| store i32 %6, ptr addrspace(11) %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 addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0i32_12_1t.i32(target("spirv.VulkanBuffer", [0 x i32], 12, 1) %1, i32 0) |
| %11 = load i32, ptr addrspace(11) %10, align 4 |
| %12 = 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) %2, i32 0) |
| store i32 %11, ptr addrspace(11) %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 addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0i32_12_1t.i32(target("spirv.VulkanBuffer", [0 x i32], 12, 1) %0, i32 %13) |
| %15 = load i32, ptr addrspace(11) %14, align 4 |
| %16 = 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) %2, i32 %9) |
| store i32 %15, ptr addrspace(11) %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 addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0i32_12_1t.i32(target("spirv.VulkanBuffer", [0 x i32], 12, 1) %2, i32 %18) |
| %20 = load i32, ptr addrspace(11) %19, align 4 |
| %add.i = add i32 %20, %17 |
| store i32 %add.i, ptr addrspace(11) %19, align 4 |
| ret void |
| } |