1; RUN: llc -march=amdgcn -mcpu=gfx900 -mattr=-xnack -verify-machineinstrs -debug-only=machine-scheduler < %s 2> %t | FileCheck --enable-var-scope --check-prefixes=CHECK,GCN %s
2; RUN: FileCheck --enable-var-scope --check-prefixes=CHECK,DBG %s < %t
3; REQUIRES: asserts
4
5; FIXME: Verifier error with xnack enabled.
6
7; CHECK-LABEL: {{^}}cluster_load_cluster_store:
8define amdgpu_kernel void @cluster_load_cluster_store(i32* noalias %lb, i32* noalias %sb) {
9bb:
10
11; DBG: Num BaseOps: {{[1-9]+}}, Offset: {{[0-9]+}}, OffsetIsScalable: {{[01]}}, Width: 8
12; DBG: Num BaseOps: {{[1-9]+}}, Offset: {{[0-9]+}}, OffsetIsScalable: {{[01]}}, Width: 8
13; DBG: Num BaseOps: {{[1-9]+}}, Offset: {{[0-9]+}}, OffsetIsScalable: {{[01]}}, Width: 4
14; DBG: Num BaseOps: {{[1-9]+}}, Offset: {{[0-9]+}}, OffsetIsScalable: {{[01]}}, Width: 4
15; DBG: Num BaseOps: {{[1-9]+}}, Offset: {{[0-9]+}}, OffsetIsScalable: {{[01]}}, Width: 4
16; DBG: Num BaseOps: {{[1-9]+}}, Offset: {{[0-9]+}}, OffsetIsScalable: {{[01]}}, Width: 4
17
18; DBG: Cluster ld/st SU(1) - SU(2)
19
20; DBG: Cluster ld/st SU([[L1:[0-9]+]]) - SU([[L2:[0-9]+]])
21; DBG: Cluster ld/st SU([[L2]]) - SU([[L3:[0-9]+]])
22; DBG: Cluster ld/st SU([[L3]]) - SU([[L4:[0-9]+]])
23; GCN:      flat_load_dword [[LD1:v[0-9]+]], v[{{[0-9:]+}}]
24; GCN-NEXT: flat_load_dword [[LD2:v[0-9]+]], v[{{[0-9:]+}}] offset:8
25; GCN-NEXT: flat_load_dword [[LD3:v[0-9]+]], v[{{[0-9:]+}}] offset:16
26; GCN-NEXT: flat_load_dword [[LD4:v[0-9]+]], v[{{[0-9:]+}}] offset:24
27  %la0 = getelementptr inbounds i32, i32* %lb, i32 0
28  %ld0 = load i32, i32* %la0
29  %la1 = getelementptr inbounds i32, i32* %lb, i32 2
30  %ld1 = load i32, i32* %la1
31  %la2 = getelementptr inbounds i32, i32* %lb, i32 4
32  %ld2 = load i32, i32* %la2
33  %la3 = getelementptr inbounds i32, i32* %lb, i32 6
34  %ld3 = load i32, i32* %la3
35
36; DBG-NOT: Cluster ld/st
37; GCN:      flat_store_dword v[{{[0-9:]+}}], [[LD1]]
38; GCN-NEXT: flat_store_dword v[{{[0-9:]+}}], [[LD2]] offset:8
39; GCN-NEXT: flat_store_dword v[{{[0-9:]+}}], [[LD3]] offset:16
40; GCN-NEXT: flat_store_dword v[{{[0-9:]+}}], [[LD4]] offset:24
41  %sa0 = getelementptr inbounds i32, i32* %sb, i32 0
42  store i32 %ld0, i32* %sa0
43  %sa1 = getelementptr inbounds i32, i32* %sb, i32 2
44  store i32 %ld1, i32* %sa1
45  %sa2 = getelementptr inbounds i32, i32* %sb, i32 4
46  store i32 %ld2, i32* %sa2
47  %sa3 = getelementptr inbounds i32, i32* %sb, i32 6
48  store i32 %ld3, i32* %sa3
49
50  ret void
51}
52
53; CHECK-LABEL: {{^}}cluster_load_valu_cluster_store:
54define amdgpu_kernel void @cluster_load_valu_cluster_store(i32* noalias %lb, i32* noalias %sb) {
55bb:
56; DBG: Num BaseOps: {{[1-9]+}}, Offset: {{[0-9]+}}, OffsetIsScalable: {{[01]}}, Width: 8
57; DBG: Num BaseOps: {{[1-9]+}}, Offset: {{[0-9]+}}, OffsetIsScalable: {{[01]}}, Width: 8
58; DBG: Num BaseOps: {{[1-9]+}}, Offset: {{[0-9]+}}, OffsetIsScalable: {{[01]}}, Width: 4
59; DBG: Num BaseOps: {{[1-9]+}}, Offset: {{[0-9]+}}, OffsetIsScalable: {{[01]}}, Width: 4
60; DBG: Num BaseOps: {{[1-9]+}}, Offset: {{[0-9]+}}, OffsetIsScalable: {{[01]}}, Width: 4
61; DBG: Num BaseOps: {{[1-9]+}}, Offset: {{[0-9]+}}, OffsetIsScalable: {{[01]}}, Width: 4
62
63; DBG: Cluster ld/st SU(1) - SU(2)
64
65; DBG: Cluster ld/st SU([[L1:[0-9]+]]) - SU([[L2:[0-9]+]])
66; DBG: Cluster ld/st SU([[L2]]) - SU([[L3:[0-9]+]])
67; DBG: Cluster ld/st SU([[L3]]) - SU([[L4:[0-9]+]])
68; GCN:      flat_load_dword [[LD1:v[0-9]+]], v[{{[0-9:]+}}]
69; GCN-NEXT: flat_load_dword [[LD2:v[0-9]+]], v[{{[0-9:]+}}] offset:8
70; GCN-NEXT: flat_load_dword [[LD3:v[0-9]+]], v[{{[0-9:]+}}] offset:16
71; GCN-NEXT: flat_load_dword [[LD4:v[0-9]+]], v[{{[0-9:]+}}] offset:24
72  %la0 = getelementptr inbounds i32, i32* %lb, i32 0
73  %ld0 = load i32, i32* %la0
74  %la1 = getelementptr inbounds i32, i32* %lb, i32 2
75  %ld1 = load i32, i32* %la1
76  %la2 = getelementptr inbounds i32, i32* %lb, i32 4
77  %ld2 = load i32, i32* %la2
78  %la3 = getelementptr inbounds i32, i32* %lb, i32 6
79  %ld3 = load i32, i32* %la3
80
81; DBG-NOT: Cluster ld/st
82; GCN:      flat_store_dword v[{{[0-9:]+}}], [[LD1]]
83; GCN:      v_add_u32_e32 [[ST2:v[0-9]+]], 1, [[LD2]]
84; GCN-NEXT: flat_store_dword v[{{[0-9:]+}}], [[LD3]] offset:16
85; GCN-NEXT: flat_store_dword v[{{[0-9:]+}}], [[ST2]] offset:8
86; GCN-NEXT: flat_store_dword v[{{[0-9:]+}}], [[LD4]] offset:24
87  %sa0 = getelementptr inbounds i32, i32* %sb, i32 0
88  store i32 %ld0, i32* %sa0
89  %sa1 = getelementptr inbounds i32, i32* %sb, i32 2
90  %add = add i32 %ld1, 1
91  store i32 %add, i32* %sa1
92  %sa2 = getelementptr inbounds i32, i32* %sb, i32 4
93  store i32 %ld2, i32* %sa2
94  %sa3 = getelementptr inbounds i32, i32* %sb, i32 6
95  store i32 %ld3, i32* %sa3
96
97  ret void
98}
99
100; Cluster loads from the same texture with different coordinates
101; CHECK-LABEL: {{^}}cluster_image_load:
102; DBG: Num BaseOps: {{[1-9]+}}, Offset: {{[0-9]+}}, OffsetIsScalable: {{[01]}}, Width: 16
103; DBG: Num BaseOps: {{[1-9]+}}, Offset: {{[0-9]+}}, OffsetIsScalable: {{[01]}}, Width: 16
104; DBG: {{^}}Cluster ld/st [[SU1:SU\([0-9]+\)]] - [[SU2:SU\([0-9]+\)]]
105; DBG: {{^}}[[SU1]]: {{.*}} IMAGE_LOAD
106; DBG: {{^}}[[SU2]]: {{.*}} IMAGE_LOAD
107; GCN:      image_load v
108; GCN-NEXT: image_load v
109define amdgpu_ps void @cluster_image_load(<8 x i32> inreg %src, <8 x i32> inreg %dst, i32 %x, i32 %y) {
110entry:
111  %x1 = add i32 %x, 1
112  %y1 = add i32 %y, 1
113  %val1 = call <4 x float> @llvm.amdgcn.image.load.mip.2d.v4f32.i32(i32 15, i32 %x1, i32 %y1, i32 0, <8 x i32> %src, i32 0, i32 0)
114  %x2 = add i32 %x, 2
115  %y2 = add i32 %y, 2
116  %val2 = call <4 x float> @llvm.amdgcn.image.load.mip.2d.v4f32.i32(i32 15, i32 %x2, i32 %y2, i32 0, <8 x i32> %src, i32 0, i32 0)
117  %val = fadd fast <4 x float> %val1, %val2
118  call void @llvm.amdgcn.image.store.2d.v4f32.i32(<4 x float> %val, i32 15, i32 %x, i32 %y, <8 x i32> %dst, i32 0, i32 0)
119  ret void
120}
121
122; Don't cluster loads from different textures
123; CHECK-LABEL: {{^}}no_cluster_image_load:
124; DBG: Num BaseOps: {{[1-9]+}}, Offset: {{[0-9]+}}, OffsetIsScalable: {{[01]}}, Width: 16
125; DBG: Num BaseOps: {{[1-9]+}}, Offset: {{[0-9]+}}, OffsetIsScalable: {{[01]}}, Width: 16
126; DBG-NOT: {{^}}Cluster ld/st
127define amdgpu_ps void @no_cluster_image_load(<8 x i32> inreg %src1, <8 x i32> inreg %src2, <8 x i32> inreg %dst, i32 %x, i32 %y) {
128entry:
129  %val1 = call <4 x float> @llvm.amdgcn.image.load.mip.2d.v4f32.i32(i32 15, i32 %x, i32 %y, i32 0, <8 x i32> %src1, i32 0, i32 0)
130  %val2 = call <4 x float> @llvm.amdgcn.image.load.mip.2d.v4f32.i32(i32 15, i32 %x, i32 %y, i32 0, <8 x i32> %src2, i32 0, i32 0)
131  %val = fadd fast <4 x float> %val1, %val2
132  call void @llvm.amdgcn.image.store.2d.v4f32.i32(<4 x float> %val, i32 15, i32 %x, i32 %y, <8 x i32> %dst, i32 0, i32 0)
133  ret void
134}
135
136; Cluster loads from the same texture and sampler with different coordinates
137; CHECK-LABEL: {{^}}cluster_image_sample:
138; DBG: Num BaseOps: {{[1-9]+}}, Offset: {{[0-9]+}}, OffsetIsScalable: {{[01]}}, Width: 16
139; DBG: Num BaseOps: {{[1-9]+}}, Offset: {{[0-9]+}}, OffsetIsScalable: {{[01]}}, Width: 16
140; DBG: {{^}}Cluster ld/st [[SU1:SU\([0-9]+\)]] - [[SU2:SU\([0-9]+\)]]
141; DBG: {{^}}[[SU1]]: {{.*}} IMAGE_SAMPLE
142; DBG: {{^}}[[SU2]]: {{.*}} IMAGE_SAMPLE
143; GCN:      image_sample_d
144; GCN-NEXT: image_sample_d
145define amdgpu_ps void @cluster_image_sample(<8 x i32> inreg %src, <4 x i32> inreg %smp, <8 x i32> inreg %dst, i32 %x, i32 %y) {
146entry:
147  %s = sitofp i32 %x to float
148  %t = sitofp i32 %y to float
149  %s1 = fadd float %s, 1.0
150  %t1 = fadd float %t, 1.0
151  %val1 = call <4 x float> @llvm.amdgcn.image.sample.d.2d.v4f32.f32(i32 15, float %s1, float %t1, float 0.0, float 0.0, float 0.0, float 0.0, <8 x i32> %src, <4 x i32> %smp, i1 false, i32 0, i32 0)
152  %s2 = fadd float %s, 2.0
153  %t2 = fadd float %t, 2.0
154  %val2 = call <4 x float> @llvm.amdgcn.image.sample.d.2d.v4f32.f32(i32 15, float %s2, float %t2, float 1.0, float 1.0, float 1.0, float 1.0, <8 x i32> %src, <4 x i32> %smp, i1 false, i32 0, i32 0)
155  %val = fadd fast <4 x float> %val1, %val2
156  call void @llvm.amdgcn.image.store.2d.v4f32.i32(<4 x float> %val, i32 15, i32 %x, i32 %y, <8 x i32> %dst, i32 0, i32 0)
157  ret void
158}
159
160declare <4 x float> @llvm.amdgcn.image.load.mip.2d.v4f32.i32(i32 immarg, i32, i32, i32, <8 x i32>, i32 immarg, i32 immarg)
161declare <4 x float> @llvm.amdgcn.image.sample.d.2d.v4f32.f32(i32, float, float, float, float, float, float, <8 x i32>, <4 x i32>, i1, i32, i32)
162declare void @llvm.amdgcn.image.store.2d.v4f32.i32(<4 x float>, i32 immarg, i32, i32, <8 x i32>, i32 immarg, i32 immarg)
163