1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -mtriple=amdgcn-amd-amdhsa < %s -amdgpu-promote-kernel-arguments -infer-address-spaces | FileCheck %s
3; RUN: opt -S -mtriple=amdgcn-amd-amdhsa < %s -passes=amdgpu-promote-kernel-arguments,infer-address-spaces | FileCheck %s
4; RUN: opt -S -mtriple=amdgcn-amd-amdhsa < %s -amdgpu-promote-kernel-arguments -infer-address-spaces | llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 | FileCheck -check-prefix=GCN %s
5
6; GCN-LABEL: ptr_nest_3:
7; GCN-COUNT-2: global_load_dwordx2
8; GCN:         global_store_dword
9define amdgpu_kernel void @ptr_nest_3(float** addrspace(1)* nocapture readonly %Arg) {
10; CHECK-LABEL: @ptr_nest_3(
11; CHECK-NEXT:  entry:
12; CHECK-NEXT:    [[I:%.*]] = tail call i32 @llvm.amdgcn.workitem.id.x()
13; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds float**, float** addrspace(1)* [[ARG:%.*]], i32 [[I]]
14; CHECK-NEXT:    [[P1_CONST:%.*]] = addrspacecast float** addrspace(1)* [[P1]] to float** addrspace(4)*
15; CHECK-NEXT:    [[P2:%.*]] = load float**, float** addrspace(4)* [[P1_CONST]], align 8
16; CHECK-NEXT:    [[TMP0:%.*]] = addrspacecast float** [[P2]] to float* addrspace(1)*
17; CHECK-NEXT:    [[TMP1:%.*]] = addrspacecast float* addrspace(1)* [[TMP0]] to float**
18; CHECK-NEXT:    [[P2_FLAT:%.*]] = addrspacecast float* addrspace(1)* [[TMP0]] to float**
19; CHECK-NEXT:    [[P2_CONST:%.*]] = addrspacecast float** [[TMP1]] to float* addrspace(4)*
20; CHECK-NEXT:    [[P3:%.*]] = load float*, float* addrspace(4)* [[P2_CONST]], align 8
21; CHECK-NEXT:    [[TMP2:%.*]] = addrspacecast float* [[P3]] to float addrspace(1)*
22; CHECK-NEXT:    store float 0.000000e+00, float addrspace(1)* [[TMP2]], align 4
23; CHECK-NEXT:    ret void
24;
25entry:
26  %i = tail call i32 @llvm.amdgcn.workitem.id.x()
27  %p1 = getelementptr inbounds float**, float** addrspace(1)* %Arg, i32 %i
28  %p2 = load float**, float** addrspace(1)* %p1, align 8
29  %p3 = load float*, float** %p2, align 8
30  store float 0.000000e+00, float* %p3, align 4
31  ret void
32}
33
34; GCN-LABEL: ptr_bitcast:
35; GCN: global_load_dwordx2
36; GCN: global_store_dword
37define amdgpu_kernel void @ptr_bitcast(float** nocapture readonly %Arg) {
38; CHECK-LABEL: @ptr_bitcast(
39; CHECK-NEXT:  entry:
40; CHECK-NEXT:    [[ARG_GLOBAL:%.*]] = addrspacecast float** [[ARG:%.*]] to float* addrspace(1)*
41; CHECK-NEXT:    [[I:%.*]] = tail call i32 @llvm.amdgcn.workitem.id.x()
42; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds float*, float* addrspace(1)* [[ARG_GLOBAL]], i32 [[I]]
43; CHECK-NEXT:    [[P1_CAST:%.*]] = bitcast float* addrspace(1)* [[P1]] to i32* addrspace(1)*
44; CHECK-NEXT:    [[TMP0:%.*]] = addrspacecast i32* addrspace(1)* [[P1_CAST]] to i32**
45; CHECK-NEXT:    [[P1_CAST_CONST:%.*]] = addrspacecast i32** [[TMP0]] to i32* addrspace(4)*
46; CHECK-NEXT:    [[P2:%.*]] = load i32*, i32* addrspace(4)* [[P1_CAST_CONST]], align 8
47; CHECK-NEXT:    [[TMP1:%.*]] = addrspacecast i32* [[P2]] to i32 addrspace(1)*
48; CHECK-NEXT:    store i32 0, i32 addrspace(1)* [[TMP1]], align 4
49; CHECK-NEXT:    ret void
50;
51entry:
52  %i = tail call i32 @llvm.amdgcn.workitem.id.x()
53  %p1 = getelementptr inbounds float*, float** %Arg, i32 %i
54  %p1.cast = bitcast float** %p1 to i32**
55  %p2 = load i32*, i32** %p1.cast, align 8
56  store i32 0, i32* %p2, align 4
57  ret void
58}
59
60%struct.S = type { float* }
61
62; GCN-LABEL: ptr_in_struct:
63; GCN: s_load_dwordx2
64; GCN: global_store_dword
65define amdgpu_kernel void @ptr_in_struct(%struct.S addrspace(1)* nocapture readonly %Arg) {
66; CHECK-LABEL: @ptr_in_struct(
67; CHECK-NEXT:  entry:
68; CHECK-NEXT:    [[P:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], [[STRUCT_S]] addrspace(1)* [[ARG:%.*]], i64 0, i32 0
69; CHECK-NEXT:    [[P_CONST:%.*]] = addrspacecast float* addrspace(1)* [[P]] to float* addrspace(4)*
70; CHECK-NEXT:    [[P1:%.*]] = load float*, float* addrspace(4)* [[P_CONST]], align 8
71; CHECK-NEXT:    [[TMP0:%.*]] = addrspacecast float* [[P1]] to float addrspace(1)*
72; CHECK-NEXT:    [[ID:%.*]] = tail call i32 @llvm.amdgcn.workitem.id.x()
73; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds float, float addrspace(1)* [[TMP0]], i32 [[ID]]
74; CHECK-NEXT:    store float 0.000000e+00, float addrspace(1)* [[ARRAYIDX]], align 4
75; CHECK-NEXT:    ret void
76;
77entry:
78  %p = getelementptr inbounds %struct.S, %struct.S addrspace(1)* %Arg, i64 0, i32 0
79  %p1 = load float*, float* addrspace(1)* %p, align 8
80  %id = tail call i32 @llvm.amdgcn.workitem.id.x()
81  %arrayidx = getelementptr inbounds float, float* %p1, i32 %id
82  store float 0.000000e+00, float* %arrayidx, align 4
83  ret void
84}
85
86@LDS = internal unnamed_addr addrspace(3) global [4 x float] undef, align 16
87
88; GCN-LABEL: flat_ptr_arg:
89; GCN-COUNT-2: global_load_dwordx2
90
91; FIXME: First load is in the constant address space and second is in global
92;        because it is clobbered by store. GPU load store vectorizer cannot
93;        combine them. Note, this does not happen with -O3 because loads are
94;        vectorized in pairs earlier and stay in the global address space.
95
96; GCN:         global_load_dword v{{[0-9]+}}, [[PTR:v\[[0-9:]+\]]], off{{$}}
97; GCN:         global_load_dwordx3 v[{{[0-9:]+}}], [[PTR]], off offset:4
98; GCN:         global_store_dword
99define amdgpu_kernel void @flat_ptr_arg(float** nocapture readonly noalias %Arg, float** nocapture noalias %Out, i32 %X) {
100; CHECK-LABEL: @flat_ptr_arg(
101; CHECK-NEXT:  entry:
102; CHECK-NEXT:    [[OUT_GLOBAL:%.*]] = addrspacecast float** [[OUT:%.*]] to float* addrspace(1)*
103; CHECK-NEXT:    [[ARG_GLOBAL:%.*]] = addrspacecast float** [[ARG:%.*]] to float* addrspace(1)*
104; CHECK-NEXT:    [[I:%.*]] = tail call i32 @llvm.amdgcn.workitem.id.x()
105; CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[I]] to i64
106; CHECK-NEXT:    [[ARRAYIDX10:%.*]] = getelementptr inbounds float*, float* addrspace(1)* [[ARG_GLOBAL]], i64 [[IDXPROM]]
107; CHECK-NEXT:    [[TMP0:%.*]] = addrspacecast float* addrspace(1)* [[ARRAYIDX10]] to float**
108; CHECK-NEXT:    [[ARRAYIDX10_CONST:%.*]] = addrspacecast float** [[TMP0]] to float* addrspace(4)*
109; CHECK-NEXT:    [[I1:%.*]] = load float*, float* addrspace(4)* [[ARRAYIDX10_CONST]], align 8
110; CHECK-NEXT:    [[TMP1:%.*]] = addrspacecast float* [[I1]] to float addrspace(1)*
111; CHECK-NEXT:    [[TMP2:%.*]] = addrspacecast float addrspace(1)* [[TMP1]] to float*
112; CHECK-NEXT:    [[I1_CONST:%.*]] = addrspacecast float* [[TMP2]] to float addrspace(4)*
113; CHECK-NEXT:    [[I2:%.*]] = load float, float addrspace(4)* [[I1_CONST]], align 4
114; CHECK-NEXT:    [[ARRAYIDX512:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[X:%.*]]
115; CHECK-NEXT:    store float [[I2]], float addrspace(3)* [[ARRAYIDX512]], align 4
116; CHECK-NEXT:    [[ARRAYIDX3_1:%.*]] = getelementptr inbounds float, float addrspace(1)* [[TMP1]], i64 1
117; CHECK-NEXT:    [[I3:%.*]] = load float, float addrspace(1)* [[ARRAYIDX3_1]], align 4
118; CHECK-NEXT:    [[ADD_1:%.*]] = add nsw i32 [[X]], 1
119; CHECK-NEXT:    [[ARRAYIDX512_1:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[ADD_1]]
120; CHECK-NEXT:    store float [[I3]], float addrspace(3)* [[ARRAYIDX512_1]], align 4
121; CHECK-NEXT:    [[ARRAYIDX3_2:%.*]] = getelementptr inbounds float, float addrspace(1)* [[TMP1]], i64 2
122; CHECK-NEXT:    [[I4:%.*]] = load float, float addrspace(1)* [[ARRAYIDX3_2]], align 4
123; CHECK-NEXT:    [[ADD_2:%.*]] = add nsw i32 [[X]], 2
124; CHECK-NEXT:    [[ARRAYIDX512_2:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[ADD_2]]
125; CHECK-NEXT:    store float [[I4]], float addrspace(3)* [[ARRAYIDX512_2]], align 4
126; CHECK-NEXT:    [[ARRAYIDX3_3:%.*]] = getelementptr inbounds float, float addrspace(1)* [[TMP1]], i64 3
127; CHECK-NEXT:    [[I5:%.*]] = load float, float addrspace(1)* [[ARRAYIDX3_3]], align 4
128; CHECK-NEXT:    [[ADD_3:%.*]] = add nsw i32 [[X]], 3
129; CHECK-NEXT:    [[ARRAYIDX512_3:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[ADD_3]]
130; CHECK-NEXT:    store float [[I5]], float addrspace(3)* [[ARRAYIDX512_3]], align 4
131; CHECK-NEXT:    [[SUB:%.*]] = add nsw i32 [[X]], -1
132; CHECK-NEXT:    [[ARRAYIDX711:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[SUB]]
133; CHECK-NEXT:    [[I6:%.*]] = load float, float addrspace(3)* [[ARRAYIDX711]], align 4
134; CHECK-NEXT:    [[ARRAYIDX11:%.*]] = getelementptr inbounds float*, float* addrspace(1)* [[OUT_GLOBAL]], i64 [[IDXPROM]]
135; CHECK-NEXT:    [[TMP3:%.*]] = addrspacecast float* addrspace(1)* [[ARRAYIDX11]] to float**
136; CHECK-NEXT:    [[ARRAYIDX11_CONST:%.*]] = addrspacecast float** [[TMP3]] to float* addrspace(4)*
137; CHECK-NEXT:    [[I7:%.*]] = load float*, float* addrspace(4)* [[ARRAYIDX11_CONST]], align 8
138; CHECK-NEXT:    [[TMP4:%.*]] = addrspacecast float* [[I7]] to float addrspace(1)*
139; CHECK-NEXT:    [[IDXPROM8:%.*]] = sext i32 [[X]] to i64
140; CHECK-NEXT:    [[ARRAYIDX9:%.*]] = getelementptr inbounds float, float addrspace(1)* [[TMP4]], i64 [[IDXPROM8]]
141; CHECK-NEXT:    store float [[I6]], float addrspace(1)* [[ARRAYIDX9]], align 4
142; CHECK-NEXT:    ret void
143;
144entry:
145  %i = tail call i32 @llvm.amdgcn.workitem.id.x()
146  %idxprom = zext i32 %i to i64
147  %arrayidx10 = getelementptr inbounds float*, float** %Arg, i64 %idxprom
148  %i1 = load float*, float** %arrayidx10, align 8
149  %i2 = load float, float* %i1, align 4
150  %arrayidx512 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %X
151  store float %i2, float addrspace(3)* %arrayidx512, align 4
152  %arrayidx3.1 = getelementptr inbounds float, float* %i1, i64 1
153  %i3 = load float, float* %arrayidx3.1, align 4
154  %add.1 = add nsw i32 %X, 1
155  %arrayidx512.1 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %add.1
156  store float %i3, float addrspace(3)* %arrayidx512.1, align 4
157  %arrayidx3.2 = getelementptr inbounds float, float* %i1, i64 2
158  %i4 = load float, float* %arrayidx3.2, align 4
159  %add.2 = add nsw i32 %X, 2
160  %arrayidx512.2 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %add.2
161  store float %i4, float addrspace(3)* %arrayidx512.2, align 4
162  %arrayidx3.3 = getelementptr inbounds float, float* %i1, i64 3
163  %i5 = load float, float* %arrayidx3.3, align 4
164  %add.3 = add nsw i32 %X, 3
165  %arrayidx512.3 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %add.3
166  store float %i5, float addrspace(3)* %arrayidx512.3, align 4
167  %sub = add nsw i32 %X, -1
168  %arrayidx711 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %sub
169  %i6 = load float, float addrspace(3)* %arrayidx711, align 4
170  %arrayidx11 = getelementptr inbounds float*, float** %Out, i64 %idxprom
171  %i7 = load float*, float** %arrayidx11, align 8
172  %idxprom8 = sext i32 %X to i64
173  %arrayidx9 = getelementptr inbounds float, float* %i7, i64 %idxprom8
174  store float %i6, float* %arrayidx9, align 4
175  ret void
176}
177
178; GCN-LABEL: global_ptr_arg:
179; GCN: global_load_dwordx2
180; GCN: global_load_dword v{{[0-9]+}}, [[PTR:v\[[0-9:]+\]]], off{{$}}
181; GCN: global_load_dwordx3 v[{{[0-9:]+}}], [[PTR]], off offset:4
182; GCN: global_store_dword
183define amdgpu_kernel void @global_ptr_arg(float* addrspace(1)* nocapture readonly %Arg, i32 %X) {
184; CHECK-LABEL: @global_ptr_arg(
185; CHECK-NEXT:  entry:
186; CHECK-NEXT:    [[I:%.*]] = tail call i32 @llvm.amdgcn.workitem.id.x()
187; CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[I]] to i64
188; CHECK-NEXT:    [[ARRAYIDX10:%.*]] = getelementptr inbounds float*, float* addrspace(1)* [[ARG:%.*]], i64 [[IDXPROM]]
189; CHECK-NEXT:    [[ARRAYIDX10_CONST:%.*]] = addrspacecast float* addrspace(1)* [[ARRAYIDX10]] to float* addrspace(4)*
190; CHECK-NEXT:    [[I1:%.*]] = load float*, float* addrspace(4)* [[ARRAYIDX10_CONST]], align 8
191; CHECK-NEXT:    [[TMP0:%.*]] = addrspacecast float* [[I1]] to float addrspace(1)*
192; CHECK-NEXT:    [[TMP1:%.*]] = addrspacecast float addrspace(1)* [[TMP0]] to float*
193; CHECK-NEXT:    [[I1_CONST:%.*]] = addrspacecast float* [[TMP1]] to float addrspace(4)*
194; CHECK-NEXT:    [[I2:%.*]] = load float, float addrspace(4)* [[I1_CONST]], align 4
195; CHECK-NEXT:    [[ARRAYIDX512:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[X:%.*]]
196; CHECK-NEXT:    store float [[I2]], float addrspace(3)* [[ARRAYIDX512]], align 4
197; CHECK-NEXT:    [[ARRAYIDX3_1:%.*]] = getelementptr inbounds float, float addrspace(1)* [[TMP0]], i64 1
198; CHECK-NEXT:    [[I3:%.*]] = load float, float addrspace(1)* [[ARRAYIDX3_1]], align 4
199; CHECK-NEXT:    [[ADD_1:%.*]] = add nsw i32 [[X]], 1
200; CHECK-NEXT:    [[ARRAYIDX512_1:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[ADD_1]]
201; CHECK-NEXT:    store float [[I3]], float addrspace(3)* [[ARRAYIDX512_1]], align 4
202; CHECK-NEXT:    [[ARRAYIDX3_2:%.*]] = getelementptr inbounds float, float addrspace(1)* [[TMP0]], i64 2
203; CHECK-NEXT:    [[I4:%.*]] = load float, float addrspace(1)* [[ARRAYIDX3_2]], align 4
204; CHECK-NEXT:    [[ADD_2:%.*]] = add nsw i32 [[X]], 2
205; CHECK-NEXT:    [[ARRAYIDX512_2:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[ADD_2]]
206; CHECK-NEXT:    store float [[I4]], float addrspace(3)* [[ARRAYIDX512_2]], align 4
207; CHECK-NEXT:    [[ARRAYIDX3_3:%.*]] = getelementptr inbounds float, float addrspace(1)* [[TMP0]], i64 3
208; CHECK-NEXT:    [[I5:%.*]] = load float, float addrspace(1)* [[ARRAYIDX3_3]], align 4
209; CHECK-NEXT:    [[ADD_3:%.*]] = add nsw i32 [[X]], 3
210; CHECK-NEXT:    [[ARRAYIDX512_3:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[ADD_3]]
211; CHECK-NEXT:    store float [[I5]], float addrspace(3)* [[ARRAYIDX512_3]], align 4
212; CHECK-NEXT:    [[SUB:%.*]] = add nsw i32 [[X]], -1
213; CHECK-NEXT:    [[ARRAYIDX711:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[SUB]]
214; CHECK-NEXT:    [[I6:%.*]] = load float, float addrspace(3)* [[ARRAYIDX711]], align 4
215; CHECK-NEXT:    [[IDXPROM8:%.*]] = sext i32 [[X]] to i64
216; CHECK-NEXT:    [[ARRAYIDX9:%.*]] = getelementptr inbounds float, float addrspace(1)* [[TMP0]], i64 [[IDXPROM8]]
217; CHECK-NEXT:    store float [[I6]], float addrspace(1)* [[ARRAYIDX9]], align 4
218; CHECK-NEXT:    ret void
219;
220entry:
221  %i = tail call i32 @llvm.amdgcn.workitem.id.x()
222  %idxprom = zext i32 %i to i64
223  %arrayidx10 = getelementptr inbounds float*, float* addrspace(1)* %Arg, i64 %idxprom
224  %i1 = load float*, float* addrspace(1)* %arrayidx10, align 8
225  %i2 = load float, float* %i1, align 4
226  %arrayidx512 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %X
227  store float %i2, float addrspace(3)* %arrayidx512, align 4
228  %arrayidx3.1 = getelementptr inbounds float, float* %i1, i64 1
229  %i3 = load float, float* %arrayidx3.1, align 4
230  %add.1 = add nsw i32 %X, 1
231  %arrayidx512.1 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %add.1
232  store float %i3, float addrspace(3)* %arrayidx512.1, align 4
233  %arrayidx3.2 = getelementptr inbounds float, float* %i1, i64 2
234  %i4 = load float, float* %arrayidx3.2, align 4
235  %add.2 = add nsw i32 %X, 2
236  %arrayidx512.2 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %add.2
237  store float %i4, float addrspace(3)* %arrayidx512.2, align 4
238  %arrayidx3.3 = getelementptr inbounds float, float* %i1, i64 3
239  %i5 = load float, float* %arrayidx3.3, align 4
240  %add.3 = add nsw i32 %X, 3
241  %arrayidx512.3 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %add.3
242  store float %i5, float addrspace(3)* %arrayidx512.3, align 4
243  %sub = add nsw i32 %X, -1
244  %arrayidx711 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %sub
245  %i6 = load float, float addrspace(3)* %arrayidx711, align 4
246  %idxprom8 = sext i32 %X to i64
247  %arrayidx9 = getelementptr inbounds float, float* %i1, i64 %idxprom8
248  store float %i6, float* %arrayidx9, align 4
249  ret void
250}
251
252; GCN-LABEL: global_ptr_arg_clobbered:
253; GCN: global_store_dwordx2
254; GCN: global_load_dwordx2
255; GCN: flat_load_dword
256; GCN: flat_store_dword
257define amdgpu_kernel void @global_ptr_arg_clobbered(float* addrspace(1)* nocapture readonly %Arg, i32 %X) {
258; CHECK-LABEL: @global_ptr_arg_clobbered(
259; CHECK-NEXT:  entry:
260; CHECK-NEXT:    [[I:%.*]] = tail call i32 @llvm.amdgcn.workitem.id.x()
261; CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[I]] to i64
262; CHECK-NEXT:    [[ARRAYIDX10:%.*]] = getelementptr inbounds float*, float* addrspace(1)* [[ARG:%.*]], i64 [[IDXPROM]]
263; CHECK-NEXT:    [[ARRAYIDX11:%.*]] = getelementptr inbounds float*, float* addrspace(1)* [[ARRAYIDX10]], i32 [[X:%.*]]
264; CHECK-NEXT:    store float* null, float* addrspace(1)* [[ARRAYIDX11]], align 4
265; CHECK-NEXT:    [[I1:%.*]] = load float*, float* addrspace(1)* [[ARRAYIDX10]], align 8
266; CHECK-NEXT:    [[I2:%.*]] = load float, float* [[I1]], align 4
267; CHECK-NEXT:    [[ARRAYIDX512:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[X]]
268; CHECK-NEXT:    store float [[I2]], float addrspace(3)* [[ARRAYIDX512]], align 4
269; CHECK-NEXT:    [[SUB:%.*]] = add nsw i32 [[X]], -1
270; CHECK-NEXT:    [[ARRAYIDX711:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[SUB]]
271; CHECK-NEXT:    [[I6:%.*]] = load float, float addrspace(3)* [[ARRAYIDX711]], align 4
272; CHECK-NEXT:    [[IDXPROM8:%.*]] = sext i32 [[X]] to i64
273; CHECK-NEXT:    [[ARRAYIDX9:%.*]] = getelementptr inbounds float, float* [[I1]], i64 [[IDXPROM8]]
274; CHECK-NEXT:    store float [[I6]], float* [[ARRAYIDX9]], align 4
275; CHECK-NEXT:    ret void
276;
277entry:
278  %i = tail call i32 @llvm.amdgcn.workitem.id.x()
279  %idxprom = zext i32 %i to i64
280  %arrayidx10 = getelementptr inbounds float*, float* addrspace(1)* %Arg, i64 %idxprom
281  %arrayidx11 = getelementptr inbounds float*, float* addrspace(1)* %arrayidx10, i32 %X
282  store float* null, float* addrspace(1)* %arrayidx11, align 4
283  %i1 = load float*, float* addrspace(1)* %arrayidx10, align 8
284  %i2 = load float, float* %i1, align 4
285  %arrayidx512 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %X
286  store float %i2, float addrspace(3)* %arrayidx512, align 4
287  %sub = add nsw i32 %X, -1
288  %arrayidx711 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %sub
289  %i6 = load float, float addrspace(3)* %arrayidx711, align 4
290  %idxprom8 = sext i32 %X to i64
291  %arrayidx9 = getelementptr inbounds float, float* %i1, i64 %idxprom8
292  store float %i6, float* %arrayidx9, align 4
293  ret void
294}
295
296; GCN-LABEL: global_ptr_arg_clobbered_after_load:
297; GCN: global_load_dwordx2
298; GCN: global_store_dwordx2
299; GCN: global_load_dword
300; GCN: global_store_dword
301define amdgpu_kernel void @global_ptr_arg_clobbered_after_load(float* addrspace(1)* nocapture readonly %Arg, i32 %X) {
302; CHECK-LABEL: @global_ptr_arg_clobbered_after_load(
303; CHECK-NEXT:  entry:
304; CHECK-NEXT:    [[I:%.*]] = tail call i32 @llvm.amdgcn.workitem.id.x()
305; CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[I]] to i64
306; CHECK-NEXT:    [[ARRAYIDX10:%.*]] = getelementptr inbounds float*, float* addrspace(1)* [[ARG:%.*]], i64 [[IDXPROM]]
307; CHECK-NEXT:    [[ARRAYIDX10_CONST:%.*]] = addrspacecast float* addrspace(1)* [[ARRAYIDX10]] to float* addrspace(4)*
308; CHECK-NEXT:    [[I1:%.*]] = load float*, float* addrspace(4)* [[ARRAYIDX10_CONST]], align 8
309; CHECK-NEXT:    [[TMP0:%.*]] = addrspacecast float* [[I1]] to float addrspace(1)*
310; CHECK-NEXT:    [[ARRAYIDX11:%.*]] = getelementptr inbounds float*, float* addrspace(1)* [[ARRAYIDX10]], i32 [[X:%.*]]
311; CHECK-NEXT:    store float* null, float* addrspace(1)* [[ARRAYIDX11]], align 4
312; CHECK-NEXT:    [[I2:%.*]] = load float, float addrspace(1)* [[TMP0]], align 4
313; CHECK-NEXT:    [[ARRAYIDX512:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[X]]
314; CHECK-NEXT:    store float [[I2]], float addrspace(3)* [[ARRAYIDX512]], align 4
315; CHECK-NEXT:    [[SUB:%.*]] = add nsw i32 [[X]], -1
316; CHECK-NEXT:    [[ARRAYIDX711:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[SUB]]
317; CHECK-NEXT:    [[I6:%.*]] = load float, float addrspace(3)* [[ARRAYIDX711]], align 4
318; CHECK-NEXT:    [[IDXPROM8:%.*]] = sext i32 [[X]] to i64
319; CHECK-NEXT:    [[ARRAYIDX9:%.*]] = getelementptr inbounds float, float addrspace(1)* [[TMP0]], i64 [[IDXPROM8]]
320; CHECK-NEXT:    store float [[I6]], float addrspace(1)* [[ARRAYIDX9]], align 4
321; CHECK-NEXT:    ret void
322;
323entry:
324  %i = tail call i32 @llvm.amdgcn.workitem.id.x()
325  %idxprom = zext i32 %i to i64
326  %arrayidx10 = getelementptr inbounds float*, float* addrspace(1)* %Arg, i64 %idxprom
327  %i1 = load float*, float* addrspace(1)* %arrayidx10, align 8
328  %arrayidx11 = getelementptr inbounds float*, float* addrspace(1)* %arrayidx10, i32 %X
329  store float* null, float* addrspace(1)* %arrayidx11, align 4
330  %i2 = load float, float* %i1, align 4
331  %arrayidx512 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %X
332  store float %i2, float addrspace(3)* %arrayidx512, align 4
333  %sub = add nsw i32 %X, -1
334  %arrayidx711 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %sub
335  %i6 = load float, float addrspace(3)* %arrayidx711, align 4
336  %idxprom8 = sext i32 %X to i64
337  %arrayidx9 = getelementptr inbounds float, float* %i1, i64 %idxprom8
338  store float %i6, float* %arrayidx9, align 4
339  ret void
340}
341
342; GCN-LABEL: ptr_nest_3_barrier:
343; GCN-COUNT-2: global_load_dwordx2
344; GCN:         global_store_dword
345define amdgpu_kernel void @ptr_nest_3_barrier(float** addrspace(1)* nocapture readonly %Arg) {
346; CHECK-LABEL: @ptr_nest_3_barrier(
347; CHECK-NEXT:  entry:
348; CHECK-NEXT:    [[I:%.*]] = tail call i32 @llvm.amdgcn.workitem.id.x()
349; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds float**, float** addrspace(1)* [[ARG:%.*]], i32 [[I]]
350; CHECK-NEXT:    tail call void @llvm.amdgcn.s.barrier()
351; CHECK-NEXT:    [[P1_CONST:%.*]] = addrspacecast float** addrspace(1)* [[P1]] to float** addrspace(4)*
352; CHECK-NEXT:    [[P2:%.*]] = load float**, float** addrspace(4)* [[P1_CONST]], align 8
353; CHECK-NEXT:    [[TMP0:%.*]] = addrspacecast float** [[P2]] to float* addrspace(1)*
354; CHECK-NEXT:    [[TMP1:%.*]] = addrspacecast float* addrspace(1)* [[TMP0]] to float**
355; CHECK-NEXT:    [[P2_FLAT:%.*]] = addrspacecast float* addrspace(1)* [[TMP0]] to float**
356; CHECK-NEXT:    [[P2_CONST:%.*]] = addrspacecast float** [[TMP1]] to float* addrspace(4)*
357; CHECK-NEXT:    [[P3:%.*]] = load float*, float* addrspace(4)* [[P2_CONST]], align 8
358; CHECK-NEXT:    [[TMP2:%.*]] = addrspacecast float* [[P3]] to float addrspace(1)*
359; CHECK-NEXT:    store float 0.000000e+00, float addrspace(1)* [[TMP2]], align 4
360; CHECK-NEXT:    ret void
361;
362entry:
363  %i = tail call i32 @llvm.amdgcn.workitem.id.x()
364  %p1 = getelementptr inbounds float**, float** addrspace(1)* %Arg, i32 %i
365  tail call void @llvm.amdgcn.s.barrier()
366  %p2 = load float**, float** addrspace(1)* %p1, align 8
367  %p3 = load float*, float** %p2, align 8
368  store float 0.000000e+00, float* %p3, align 4
369  ret void
370}
371
372; GCN-LABEL: flat_ptr_nest_2:
373; GCN: s_lshl_b64
374; GCN: s_load_dwordx2
375; GCN: global_store_dword
376define amdgpu_kernel void @flat_ptr_nest_2(float** nocapture readonly %Arg, i32 %i) {
377; CHECK-LABEL: @flat_ptr_nest_2(
378; CHECK-NEXT:  entry:
379; CHECK-NEXT:    [[ARG_GLOBAL:%.*]] = addrspacecast float** [[ARG:%.*]] to float* addrspace(1)*
380; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds float*, float* addrspace(1)* [[ARG_GLOBAL]], i32 [[I:%.*]]
381; CHECK-NEXT:    [[TMP0:%.*]] = addrspacecast float* addrspace(1)* [[P1]] to float**
382; CHECK-NEXT:    [[P1_CONST:%.*]] = addrspacecast float** [[TMP0]] to float* addrspace(4)*
383; CHECK-NEXT:    [[P2:%.*]] = load float*, float* addrspace(4)* [[P1_CONST]], align 8
384; CHECK-NEXT:    [[TMP1:%.*]] = addrspacecast float* [[P2]] to float addrspace(1)*
385; CHECK-NEXT:    store float 0.000000e+00, float addrspace(1)* [[TMP1]], align 4
386; CHECK-NEXT:    ret void
387;
388entry:
389  %p1 = getelementptr inbounds float*, float** %Arg, i32 %i
390  %p2 = load float*, float** %p1, align 8
391  store float 0.000000e+00, float* %p2, align 4
392  ret void
393}
394
395; GCN-LABEL: const_ptr_nest_3:
396; GCN: s_lshl_b64
397; GCN: s_load_dwordx2
398; GCN: s_load_dwordx2
399; GCN: global_store_dword
400define amdgpu_kernel void @const_ptr_nest_3(float* addrspace(4)* addrspace(4)* nocapture readonly %Arg, i32 %i) {
401; CHECK-LABEL: @const_ptr_nest_3(
402; CHECK-NEXT:  entry:
403; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds float* addrspace(4)*, float* addrspace(4)* addrspace(4)* [[ARG:%.*]], i32 [[I:%.*]]
404; CHECK-NEXT:    [[P2:%.*]] = load float* addrspace(4)*, float* addrspace(4)* addrspace(4)* [[P1]], align 8
405; CHECK-NEXT:    [[P3:%.*]] = load float*, float* addrspace(4)* [[P2]], align 8
406; CHECK-NEXT:    [[TMP0:%.*]] = addrspacecast float* [[P3]] to float addrspace(1)*
407; CHECK-NEXT:    store float 0.000000e+00, float addrspace(1)* [[TMP0]], align 4
408; CHECK-NEXT:    ret void
409;
410entry:
411  %p1 = getelementptr inbounds float* addrspace(4)*, float* addrspace(4)* addrspace(4)* %Arg, i32 %i
412  %p2 = load float* addrspace(4)*, float * addrspace(4)* addrspace(4)* %p1, align 8
413  %p3 = load float*, float* addrspace(4)* %p2, align 8
414  store float 0.000000e+00, float* %p3, align 4
415  ret void
416}
417
418; GCN-LABEL: cast_from_const_const_ptr_nest_3:
419; GCN: s_lshl_b64
420; GCN: s_load_dwordx2
421; GCN: s_load_dwordx2
422; GCN: global_store_dword
423define amdgpu_kernel void @cast_from_const_const_ptr_nest_3(float* addrspace(4)* addrspace(4)* nocapture readonly %Arg, i32 %i) {
424; CHECK-LABEL: @cast_from_const_const_ptr_nest_3(
425; CHECK-NEXT:  entry:
426; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds float* addrspace(4)*, float* addrspace(4)* addrspace(4)* [[ARG:%.*]], i32 [[I:%.*]]
427; CHECK-NEXT:    [[P2:%.*]] = load float* addrspace(4)*, float* addrspace(4)* addrspace(4)* [[P1]], align 8
428; CHECK-NEXT:    [[P3:%.*]] = load float*, float* addrspace(4)* [[P2]], align 8
429; CHECK-NEXT:    [[P3_GLOBAL:%.*]] = addrspacecast float* [[P3]] to float addrspace(1)*
430; CHECK-NEXT:    store float 0.000000e+00, float addrspace(1)* [[P3_GLOBAL]], align 4
431; CHECK-NEXT:    ret void
432;
433entry:
434  %p1 = getelementptr inbounds float* addrspace(4)*, float* addrspace(4)* addrspace(4)* %Arg, i32 %i
435  %a1 = addrspacecast float* addrspace(4)* addrspace(4)* %p1 to float* addrspace(4)**
436  %p2 = load float* addrspace(4)*, float* addrspace(4)** %a1, align 8
437  %a2 = addrspacecast float* addrspace(4)* %p2 to float**
438  %p3 = load float*, float** %a2, align 8
439  store float 0.000000e+00, float* %p3, align 4
440  ret void
441}
442
443; GCN-LABEL: flat_ptr_volatile_load:
444; GCN: s_lshl_b64
445; GCN: flat_load_dwordx2
446; GCN: global_store_dword
447define amdgpu_kernel void @flat_ptr_volatile_load(float** nocapture readonly %Arg, i32 %i) {
448; CHECK-LABEL: @flat_ptr_volatile_load(
449; CHECK-NEXT:  entry:
450; CHECK-NEXT:    [[ARG_GLOBAL:%.*]] = addrspacecast float** [[ARG:%.*]] to float* addrspace(1)*
451; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds float*, float* addrspace(1)* [[ARG_GLOBAL]], i32 [[I:%.*]]
452; CHECK-NEXT:    [[TMP0:%.*]] = addrspacecast float* addrspace(1)* [[P1]] to float**
453; CHECK-NEXT:    [[P2:%.*]] = load volatile float*, float** [[TMP0]], align 8
454; CHECK-NEXT:    [[P2_GLOBAL:%.*]] = addrspacecast float* [[P2]] to float addrspace(1)*
455; CHECK-NEXT:    store float 0.000000e+00, float addrspace(1)* [[P2_GLOBAL]], align 4
456; CHECK-NEXT:    ret void
457;
458entry:
459  %p1 = getelementptr inbounds float*, float** %Arg, i32 %i
460  %p2 = load volatile float*, float** %p1, align 8
461  store float 0.000000e+00, float* %p2, align 4
462  ret void
463}
464
465; GCN-LABEL: flat_ptr_atomic_load:
466; GCN: s_lshl_b64
467; GCN: global_load_dwordx2
468; GCN: global_store_dword
469define amdgpu_kernel void @flat_ptr_atomic_load(float** nocapture readonly %Arg, i32 %i) {
470; CHECK-LABEL: @flat_ptr_atomic_load(
471; CHECK-NEXT:  entry:
472; CHECK-NEXT:    [[ARG_GLOBAL:%.*]] = addrspacecast float** [[ARG:%.*]] to float* addrspace(1)*
473; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds float*, float* addrspace(1)* [[ARG_GLOBAL]], i32 [[I:%.*]]
474; CHECK-NEXT:    [[P2:%.*]] = load atomic float*, float* addrspace(1)* [[P1]] monotonic, align 8
475; CHECK-NEXT:    [[P2_GLOBAL:%.*]] = addrspacecast float* [[P2]] to float addrspace(1)*
476; CHECK-NEXT:    store float 0.000000e+00, float addrspace(1)* [[P2_GLOBAL]], align 4
477; CHECK-NEXT:    ret void
478;
479entry:
480  %p1 = getelementptr inbounds float*, float** %Arg, i32 %i
481  %p2 = load atomic float*, float** %p1 monotonic, align 8
482  store float 0.000000e+00, float* %p2, align 4
483  ret void
484}
485
486; GCN-LABEL: cast_changing_pointee_type:
487; GCN: s_lshl_b64
488; GCN: s_load_dwordx2
489; GCN: s_load_dwordx2
490; GCN: global_store_dword
491define amdgpu_kernel void @cast_changing_pointee_type(float* addrspace(1)* addrspace(1)* nocapture readonly %Arg, i32 %i) {
492; CHECK-LABEL: @cast_changing_pointee_type(
493; CHECK-NEXT:  entry:
494; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds float* addrspace(1)*, float* addrspace(1)* addrspace(1)* [[ARG:%.*]], i32 [[I:%.*]]
495; CHECK-NEXT:    [[A1:%.*]] = bitcast float* addrspace(1)* addrspace(1)* [[P1]] to i32* addrspace(1)* addrspace(1)*
496; CHECK-NEXT:    [[TMP0:%.*]] = addrspacecast float* addrspace(1)* addrspace(1)* [[P1]] to i32* addrspace(1)**
497; CHECK-NEXT:    [[A1_CONST:%.*]] = addrspacecast i32* addrspace(1)** [[TMP0]] to i32* addrspace(1)* addrspace(4)*
498; CHECK-NEXT:    [[P2:%.*]] = load i32* addrspace(1)*, i32* addrspace(1)* addrspace(4)* [[A1_CONST]], align 8
499; CHECK-NEXT:    [[A2:%.*]] = bitcast i32* addrspace(1)* [[P2]] to float* addrspace(1)*
500; CHECK-NEXT:    [[TMP1:%.*]] = addrspacecast i32* addrspace(1)* [[P2]] to float**
501; CHECK-NEXT:    [[A2_CONST:%.*]] = addrspacecast float** [[TMP1]] to float* addrspace(4)*
502; CHECK-NEXT:    [[P3:%.*]] = load float*, float* addrspace(4)* [[A2_CONST]], align 8
503; CHECK-NEXT:    [[TMP2:%.*]] = addrspacecast float* [[P3]] to float addrspace(1)*
504; CHECK-NEXT:    store float 0.000000e+00, float addrspace(1)* [[TMP2]], align 4
505; CHECK-NEXT:    ret void
506;
507entry:
508  %p1 = getelementptr inbounds float* addrspace(1)*, float* addrspace(1)* addrspace(1)* %Arg, i32 %i
509  %a1 = addrspacecast float* addrspace(1)* addrspace(1)* %p1 to i32* addrspace(1)**
510  %p2 = load i32* addrspace(1)*, i32* addrspace(1)** %a1, align 8
511  %a2 = addrspacecast i32* addrspace(1)* %p2 to float**
512  %p3 = load float*, float** %a2, align 8
513  store float 0.000000e+00, float* %p3, align 4
514  ret void
515}
516
517declare i32 @llvm.amdgcn.workitem.id.x()
518declare void @llvm.amdgcn.s.barrier()
519