1; RUN: llc -march=amdgcn -mcpu=gfx900 -global-isel=0 -verify-machineinstrs -stop-after=finalize-isel -o - %s | FileCheck -check-prefixes=GCN,SDAG %s
2; RUN: llc -march=amdgcn -mcpu=gfx900 -global-isel=1 -verify-machineinstrs -stop-after=finalize-isel -o - %s | FileCheck -check-prefixes=GCN,GISEL %s
3
4@0 = external dso_local addrspace(4) constant [4 x <2 x float>]
5@1 = external dso_local addrspace(4) constant i32
6
7; Test that DAG->DAG ISel is able to pick up the S_LOAD_DWORDX4_SGPR instruction that fetches the offset
8; from a register.
9; GCN-LABEL: name: test_load_zext
10; GCN: %[[OFFSET:[0-9]+]]:sreg_32 = S_MOV_B32 target-flags(amdgpu-abs32-lo) @DescriptorBuffer
11; SDAG: %{{[0-9]+}}:sgpr_128 = S_LOAD_DWORDX4_SGPR killed %{{[0-9]+}}, killed %[[OFFSET]], 0 :: (invariant load (s128) from %ir.13, addrspace 4)
12; GISEL: %{{[0-9]+}}:sgpr_128 = S_LOAD_DWORDX4_SGPR %{{[0-9]+}}, %[[OFFSET]], 0 :: (invariant load (<4 x s32>) from {{.*}}, addrspace 4)
13define amdgpu_cs void @test_load_zext(i32 inreg %0, i32 inreg %1, i32 inreg %resNode0, i32 inreg %resNode1, <3 x i32> inreg %2, i32 inreg %3, <3 x i32> %4) local_unnamed_addr #2 {
14.entry:
15  %5 = call i64 @llvm.amdgcn.s.getpc() #3
16  %6 = bitcast i64 %5 to <2 x i32>
17  %7 = insertelement <2 x i32> %6, i32 %resNode0, i32 0
18  %8 = bitcast <2 x i32> %7 to i64
19  %9 = inttoptr i64 %8 to [4294967295 x i8] addrspace(4)*
20  %10 = call i32 @llvm.amdgcn.reloc.constant(metadata !4)
21  %11 = zext i32 %10 to i64
22  %12 = getelementptr [4294967295 x i8], [4294967295 x i8] addrspace(4)* %9, i64 0, i64 %11
23  %13 = bitcast i8 addrspace(4)* %12 to <4 x i32> addrspace(4)*, !amdgpu.uniform !5
24  %14 = load <4 x i32>, <4 x i32> addrspace(4)* %13, align 16, !invariant.load !5
25  %15 = call <4 x i32> @llvm.amdgcn.s.buffer.load.v4i32(<4 x i32> %14, i32 0, i32 0)
26  call void @llvm.amdgcn.raw.buffer.store.v4i32(<4 x i32> %15, <4 x i32> %14, i32 0, i32 0, i32 0)
27  ret void
28}
29
30; Make sure we match constant bases with register offests, in which case
31; the base may be the RHS operand of the load in SDAG.
32; GCN-LABEL: name: test_complex_reg_offset
33; GCN-DAG: %[[BASE:.*]]:sreg_64 = SI_PC_ADD_REL_OFFSET target-flags(amdgpu-rel32-lo) @0 + 4,
34; GCN-DAG: %[[OFFSET:.*]]:sreg_32 = S_LSHL_B32
35; SDAG: S_LOAD_DWORD_SGPR killed %[[BASE]], killed %[[OFFSET]],
36; GISEL: S_LOAD_DWORD_SGPR %[[BASE]], %[[OFFSET]],
37define amdgpu_ps void @test_complex_reg_offset(float addrspace(1)* %out) {
38  %i = load i32, i32 addrspace(4)* @1
39  %i1 = and i32 %i, 3
40  %i2 = zext i32 %i1 to i64
41  %i3 = getelementptr [4 x <2 x float>], [4 x <2 x float>] addrspace(4)* @0, i64 0, i64 %i2, i64 0
42  %i4 = load float, float addrspace(4)* %i3, align 4
43  store float %i4, float addrspace(1)* %out
44  ret void
45}
46
47; GCN-LABEL: name: test_sgpr_plus_imm_offset
48; SDAG-DAG: %[[BASE0:.*]]:sgpr_32 = COPY $sgpr0
49; SDAG-DAG: %[[BASE1:.*]]:sgpr_32 = COPY $sgpr1
50; SDAG-DAG: %[[OFFSET:.*]]:sgpr_32 = COPY $sgpr2
51; SDAG-DAG: %[[BASE:.*]]:sgpr_64 = REG_SEQUENCE %[[BASE0]], %subreg.sub0, %[[BASE1]], %subreg.sub1
52; SDAG: S_LOAD_DWORD_SGPR_IMM killed %[[BASE]], %[[OFFSET]], 16,
53; GISEL-DAG: %[[BASE0:.*]]:sreg_32 = COPY $sgpr0
54; GISEL-DAG: %[[BASE1:.*]]:sreg_32 = COPY $sgpr1
55; GISEL-DAG: %[[OFFSET:.*]]:sreg_32 = COPY $sgpr2
56; GISEL-DAG: %[[BASE:.*]]:sreg_64 = REG_SEQUENCE %[[BASE0]], %subreg.sub0, %[[BASE1]], %subreg.sub1
57; GISEL: S_LOAD_DWORD_SGPR_IMM %[[BASE]], %[[OFFSET]], 16,
58define amdgpu_ps void @test_sgpr_plus_imm_offset(i8 addrspace(4)* inreg %base, i32 inreg %offset,
59                                                 i32 addrspace(1)* inreg %out) {
60  %v1 = getelementptr i8, i8 addrspace(4)* %base, i64 16
61  %v2 = zext i32 %offset to i64
62  %v3 = getelementptr i8, i8 addrspace(4)* %v1, i64 %v2
63  %v4 = bitcast i8 addrspace(4)* %v3 to i32 addrspace(4)*
64  %v5 = load i32, i32 addrspace(4)* %v4, align 4
65  store i32 %v5, i32 addrspace(1)* %out, align 4
66  ret void
67}
68
69; GCN-LABEL: name: test_sgpr_plus_imm_offset_x2
70; SDAG-DAG: %[[BASE0:.*]]:sgpr_32 = COPY $sgpr0
71; SDAG-DAG: %[[BASE1:.*]]:sgpr_32 = COPY $sgpr1
72; SDAG-DAG: %[[OFFSET:.*]]:sgpr_32 = COPY $sgpr2
73; SDAG-DAG: %[[BASE:.*]]:sgpr_64 = REG_SEQUENCE %[[BASE0]], %subreg.sub0, %[[BASE1]], %subreg.sub1
74; SDAG: S_LOAD_DWORDX2_SGPR_IMM killed %[[BASE]], %[[OFFSET]], 16,
75; GISEL-DAG: %[[BASE0:.*]]:sreg_32 = COPY $sgpr0
76; GISEL-DAG: %[[BASE1:.*]]:sreg_32 = COPY $sgpr1
77; GISEL-DAG: %[[OFFSET:.*]]:sreg_32 = COPY $sgpr2
78; GISEL-DAG: %[[BASE:.*]]:sreg_64 = REG_SEQUENCE %[[BASE0]], %subreg.sub0, %[[BASE1]], %subreg.sub1
79; GISEL: S_LOAD_DWORDX2_SGPR_IMM %[[BASE]], %[[OFFSET]], 16,
80define amdgpu_ps void @test_sgpr_plus_imm_offset_x2(i8 addrspace(4)* inreg %base, i32 inreg %offset,
81                                                    <2 x i32> addrspace(1)* inreg %out) {
82  %v1 = getelementptr i8, i8 addrspace(4)* %base, i64 16
83  %v2 = zext i32 %offset to i64
84  %v3 = getelementptr i8, i8 addrspace(4)* %v1, i64 %v2
85  %v4 = bitcast i8 addrspace(4)* %v3 to <2 x i32> addrspace(4)*
86  %v5 = load <2 x i32>, <2 x i32> addrspace(4)* %v4, align 4
87  store <2 x i32> %v5, <2 x i32> addrspace(1)* %out, align 4
88  ret void
89}
90
91declare void @llvm.amdgcn.raw.buffer.store.v4i32(<4 x i32>, <4 x i32>, i32, i32, i32 immarg) #1
92
93; Function Attrs: nounwind readnone speculatable
94declare i32 @llvm.amdgcn.reloc.constant(metadata) #3
95
96; Function Attrs: nounwind readnone speculatable
97declare i64 @llvm.amdgcn.s.getpc() #3
98
99; Function Attrs: nounwind readnone
100declare <4 x i32> @llvm.amdgcn.s.buffer.load.v4i32(<4 x i32>, i32, i32 immarg) #1
101
102attributes #0 = { argmemonly nounwind willreturn }
103attributes #1 = { nounwind readnone }
104attributes #2 = { nounwind "amdgpu-unroll-threshold"="700" }
105attributes #3 = { nounwind readnone speculatable }
106attributes #4 = { nounwind writeonly }
107
108!llpc.compute.mode = !{!0}
109!llpc.options = !{!1}
110!llpc.options.CS = !{!2}
111!llpc.user.data.nodes = !{!3, !4, !5, !6}
112!amdgpu.pal.metadata.msgpack = !{!7}
113
114!0 = !{i32 2, i32 3, i32 1}
115!1 = !{i32 245227952, i32 996822128, i32 2024708198, i32 497230408}
116!2 = !{i32 1381820427, i32 1742110173, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 64}
117!3 = !{!"DescriptorTableVaPtr", i32 0, i32 1, i32 1}
118!4 = !{!"DescriptorBuffer", i32 4, i32 8, i32 0, i32 0}
119!5 = !{!"DescriptorTableVaPtr", i32 1, i32 1, i32 1}
120!6 = !{!"DescriptorBuffer", i32 4, i32 8, i32 1, i32 0}
121!7 = !{!"\82\B0amdpal.pipelines\91\88\A4.api\A6Vulkan\B0.hardware_stages\81\A3.cs\82\AB.sgpr_limith\AB.vgpr_limit\CD\01\00\B7.internal_pipeline_hash\92\CF;jLp\0E\9D\E1\B0\CF\1D\A3\22Hx\AE\98f\AA.registers\88\CD.\07\02\CD.\08\03\CD.\09\01\CD.\12\CE\00,\00\00\CD.\13\CD\0F\88\CD.@\CE\10\00\00\00\CD.B\00\CD.C\01\A8.shaders\81\A8.compute\82\B0.api_shader_hash\92\CFg\D6}\DDR\\\E8\0B\00\B1.hardware_mapping\91\A3.cs\B0.spill_threshold\CE\FF\FF\FF\FF\A5.type\A2Cs\B0.user_data_limit\02\AEamdpal.version\92\02\03"}
122!8 = !{i32 5}
123!9 = !{!"doff_0_0_b"}
124!10 = !{}
125!11 = !{!"doff_1_0_b"}
126