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; GCN:         global_load_dwordx4
91; GCN:         global_store_dword
92define amdgpu_kernel void @flat_ptr_arg(float** nocapture readonly noalias %Arg, float** nocapture noalias %Out, i32 %X) {
93; CHECK-LABEL: @flat_ptr_arg(
94; CHECK-NEXT:  entry:
95; CHECK-NEXT:    [[OUT_GLOBAL:%.*]] = addrspacecast float** [[OUT:%.*]] to float* addrspace(1)*
96; CHECK-NEXT:    [[ARG_GLOBAL:%.*]] = addrspacecast float** [[ARG:%.*]] to float* addrspace(1)*
97; CHECK-NEXT:    [[I:%.*]] = tail call i32 @llvm.amdgcn.workitem.id.x()
98; CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[I]] to i64
99; CHECK-NEXT:    [[ARRAYIDX10:%.*]] = getelementptr inbounds float*, float* addrspace(1)* [[ARG_GLOBAL]], i64 [[IDXPROM]]
100; CHECK-NEXT:    [[TMP0:%.*]] = addrspacecast float* addrspace(1)* [[ARRAYIDX10]] to float**
101; CHECK-NEXT:    [[ARRAYIDX10_CONST:%.*]] = addrspacecast float** [[TMP0]] to float* addrspace(4)*
102; CHECK-NEXT:    [[I1:%.*]] = load float*, float* addrspace(4)* [[ARRAYIDX10_CONST]], align 8
103; CHECK-NEXT:    [[TMP1:%.*]] = addrspacecast float* [[I1]] to float addrspace(1)*
104; CHECK-NEXT:    [[TMP2:%.*]] = addrspacecast float addrspace(1)* [[TMP1]] to float*
105; CHECK-NEXT:    [[I1_CONST:%.*]] = addrspacecast float* [[TMP2]] to float addrspace(4)*
106; CHECK-NEXT:    [[I2:%.*]] = load float, float addrspace(4)* [[I1_CONST]], align 4
107; CHECK-NEXT:    [[ARRAYIDX512:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[X:%.*]]
108; CHECK-NEXT:    store float [[I2]], float addrspace(3)* [[ARRAYIDX512]], align 4
109; CHECK-NEXT:    [[ARRAYIDX3_1:%.*]] = getelementptr inbounds float, float addrspace(1)* [[TMP1]], i64 1
110; CHECK-NEXT:    [[I3:%.*]] = load float, float addrspace(1)* [[ARRAYIDX3_1]], align 4
111; CHECK-NEXT:    [[ADD_1:%.*]] = add nsw i32 [[X]], 1
112; CHECK-NEXT:    [[ARRAYIDX512_1:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[ADD_1]]
113; CHECK-NEXT:    store float [[I3]], float addrspace(3)* [[ARRAYIDX512_1]], align 4
114; CHECK-NEXT:    [[ARRAYIDX3_2:%.*]] = getelementptr inbounds float, float addrspace(1)* [[TMP1]], i64 2
115; CHECK-NEXT:    [[I4:%.*]] = load float, float addrspace(1)* [[ARRAYIDX3_2]], align 4
116; CHECK-NEXT:    [[ADD_2:%.*]] = add nsw i32 [[X]], 2
117; CHECK-NEXT:    [[ARRAYIDX512_2:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[ADD_2]]
118; CHECK-NEXT:    store float [[I4]], float addrspace(3)* [[ARRAYIDX512_2]], align 4
119; CHECK-NEXT:    [[ARRAYIDX3_3:%.*]] = getelementptr inbounds float, float addrspace(1)* [[TMP1]], i64 3
120; CHECK-NEXT:    [[I5:%.*]] = load float, float addrspace(1)* [[ARRAYIDX3_3]], align 4
121; CHECK-NEXT:    [[ADD_3:%.*]] = add nsw i32 [[X]], 3
122; CHECK-NEXT:    [[ARRAYIDX512_3:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[ADD_3]]
123; CHECK-NEXT:    store float [[I5]], float addrspace(3)* [[ARRAYIDX512_3]], align 4
124; CHECK-NEXT:    [[SUB:%.*]] = add nsw i32 [[X]], -1
125; CHECK-NEXT:    [[ARRAYIDX711:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[SUB]]
126; CHECK-NEXT:    [[I6:%.*]] = load float, float addrspace(3)* [[ARRAYIDX711]], align 4
127; CHECK-NEXT:    [[ARRAYIDX11:%.*]] = getelementptr inbounds float*, float* addrspace(1)* [[OUT_GLOBAL]], i64 [[IDXPROM]]
128; CHECK-NEXT:    [[TMP3:%.*]] = addrspacecast float* addrspace(1)* [[ARRAYIDX11]] to float**
129; CHECK-NEXT:    [[ARRAYIDX11_CONST:%.*]] = addrspacecast float** [[TMP3]] to float* addrspace(4)*
130; CHECK-NEXT:    [[I7:%.*]] = load float*, float* addrspace(4)* [[ARRAYIDX11_CONST]], align 8
131; CHECK-NEXT:    [[TMP4:%.*]] = addrspacecast float* [[I7]] to float addrspace(1)*
132; CHECK-NEXT:    [[IDXPROM8:%.*]] = sext i32 [[X]] to i64
133; CHECK-NEXT:    [[ARRAYIDX9:%.*]] = getelementptr inbounds float, float addrspace(1)* [[TMP4]], i64 [[IDXPROM8]]
134; CHECK-NEXT:    store float [[I6]], float addrspace(1)* [[ARRAYIDX9]], align 4
135; CHECK-NEXT:    ret void
136;
137entry:
138  %i = tail call i32 @llvm.amdgcn.workitem.id.x()
139  %idxprom = zext i32 %i to i64
140  %arrayidx10 = getelementptr inbounds float*, float** %Arg, i64 %idxprom
141  %i1 = load float*, float** %arrayidx10, align 8
142  %i2 = load float, float* %i1, align 4
143  %arrayidx512 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %X
144  store float %i2, float addrspace(3)* %arrayidx512, align 4
145  %arrayidx3.1 = getelementptr inbounds float, float* %i1, i64 1
146  %i3 = load float, float* %arrayidx3.1, align 4
147  %add.1 = add nsw i32 %X, 1
148  %arrayidx512.1 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %add.1
149  store float %i3, float addrspace(3)* %arrayidx512.1, align 4
150  %arrayidx3.2 = getelementptr inbounds float, float* %i1, i64 2
151  %i4 = load float, float* %arrayidx3.2, align 4
152  %add.2 = add nsw i32 %X, 2
153  %arrayidx512.2 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %add.2
154  store float %i4, float addrspace(3)* %arrayidx512.2, align 4
155  %arrayidx3.3 = getelementptr inbounds float, float* %i1, i64 3
156  %i5 = load float, float* %arrayidx3.3, align 4
157  %add.3 = add nsw i32 %X, 3
158  %arrayidx512.3 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %add.3
159  store float %i5, float addrspace(3)* %arrayidx512.3, align 4
160  %sub = add nsw i32 %X, -1
161  %arrayidx711 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %sub
162  %i6 = load float, float addrspace(3)* %arrayidx711, align 4
163  %arrayidx11 = getelementptr inbounds float*, float** %Out, i64 %idxprom
164  %i7 = load float*, float** %arrayidx11, align 8
165  %idxprom8 = sext i32 %X to i64
166  %arrayidx9 = getelementptr inbounds float, float* %i7, i64 %idxprom8
167  store float %i6, float* %arrayidx9, align 4
168  ret void
169}
170
171; GCN-LABEL: global_ptr_arg:
172; GCN: global_load_dwordx2
173; GCN: global_load_dwordx4
174; GCN: global_store_dword
175define amdgpu_kernel void @global_ptr_arg(float* addrspace(1)* nocapture readonly %Arg, i32 %X) {
176; CHECK-LABEL: @global_ptr_arg(
177; CHECK-NEXT:  entry:
178; CHECK-NEXT:    [[I:%.*]] = tail call i32 @llvm.amdgcn.workitem.id.x()
179; CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[I]] to i64
180; CHECK-NEXT:    [[ARRAYIDX10:%.*]] = getelementptr inbounds float*, float* addrspace(1)* [[ARG:%.*]], i64 [[IDXPROM]]
181; CHECK-NEXT:    [[ARRAYIDX10_CONST:%.*]] = addrspacecast float* addrspace(1)* [[ARRAYIDX10]] to float* addrspace(4)*
182; CHECK-NEXT:    [[I1:%.*]] = load float*, float* addrspace(4)* [[ARRAYIDX10_CONST]], align 8
183; CHECK-NEXT:    [[TMP0:%.*]] = addrspacecast float* [[I1]] to float addrspace(1)*
184; CHECK-NEXT:    [[TMP1:%.*]] = addrspacecast float addrspace(1)* [[TMP0]] to float*
185; CHECK-NEXT:    [[I1_CONST:%.*]] = addrspacecast float* [[TMP1]] to float addrspace(4)*
186; CHECK-NEXT:    [[I2:%.*]] = load float, float addrspace(4)* [[I1_CONST]], align 4
187; CHECK-NEXT:    [[ARRAYIDX512:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[X:%.*]]
188; CHECK-NEXT:    store float [[I2]], float addrspace(3)* [[ARRAYIDX512]], align 4
189; CHECK-NEXT:    [[ARRAYIDX3_1:%.*]] = getelementptr inbounds float, float addrspace(1)* [[TMP0]], i64 1
190; CHECK-NEXT:    [[I3:%.*]] = load float, float addrspace(1)* [[ARRAYIDX3_1]], align 4
191; CHECK-NEXT:    [[ADD_1:%.*]] = add nsw i32 [[X]], 1
192; CHECK-NEXT:    [[ARRAYIDX512_1:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[ADD_1]]
193; CHECK-NEXT:    store float [[I3]], float addrspace(3)* [[ARRAYIDX512_1]], align 4
194; CHECK-NEXT:    [[ARRAYIDX3_2:%.*]] = getelementptr inbounds float, float addrspace(1)* [[TMP0]], i64 2
195; CHECK-NEXT:    [[I4:%.*]] = load float, float addrspace(1)* [[ARRAYIDX3_2]], align 4
196; CHECK-NEXT:    [[ADD_2:%.*]] = add nsw i32 [[X]], 2
197; CHECK-NEXT:    [[ARRAYIDX512_2:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[ADD_2]]
198; CHECK-NEXT:    store float [[I4]], float addrspace(3)* [[ARRAYIDX512_2]], align 4
199; CHECK-NEXT:    [[ARRAYIDX3_3:%.*]] = getelementptr inbounds float, float addrspace(1)* [[TMP0]], i64 3
200; CHECK-NEXT:    [[I5:%.*]] = load float, float addrspace(1)* [[ARRAYIDX3_3]], align 4
201; CHECK-NEXT:    [[ADD_3:%.*]] = add nsw i32 [[X]], 3
202; CHECK-NEXT:    [[ARRAYIDX512_3:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[ADD_3]]
203; CHECK-NEXT:    store float [[I5]], float addrspace(3)* [[ARRAYIDX512_3]], align 4
204; CHECK-NEXT:    [[SUB:%.*]] = add nsw i32 [[X]], -1
205; CHECK-NEXT:    [[ARRAYIDX711:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[SUB]]
206; CHECK-NEXT:    [[I6:%.*]] = load float, float addrspace(3)* [[ARRAYIDX711]], align 4
207; CHECK-NEXT:    [[IDXPROM8:%.*]] = sext i32 [[X]] to i64
208; CHECK-NEXT:    [[ARRAYIDX9:%.*]] = getelementptr inbounds float, float addrspace(1)* [[TMP0]], i64 [[IDXPROM8]]
209; CHECK-NEXT:    store float [[I6]], float addrspace(1)* [[ARRAYIDX9]], align 4
210; CHECK-NEXT:    ret void
211;
212entry:
213  %i = tail call i32 @llvm.amdgcn.workitem.id.x()
214  %idxprom = zext i32 %i to i64
215  %arrayidx10 = getelementptr inbounds float*, float* addrspace(1)* %Arg, i64 %idxprom
216  %i1 = load float*, float* addrspace(1)* %arrayidx10, align 8
217  %i2 = load float, float* %i1, align 4
218  %arrayidx512 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %X
219  store float %i2, float addrspace(3)* %arrayidx512, align 4
220  %arrayidx3.1 = getelementptr inbounds float, float* %i1, i64 1
221  %i3 = load float, float* %arrayidx3.1, align 4
222  %add.1 = add nsw i32 %X, 1
223  %arrayidx512.1 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %add.1
224  store float %i3, float addrspace(3)* %arrayidx512.1, align 4
225  %arrayidx3.2 = getelementptr inbounds float, float* %i1, i64 2
226  %i4 = load float, float* %arrayidx3.2, align 4
227  %add.2 = add nsw i32 %X, 2
228  %arrayidx512.2 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %add.2
229  store float %i4, float addrspace(3)* %arrayidx512.2, align 4
230  %arrayidx3.3 = getelementptr inbounds float, float* %i1, i64 3
231  %i5 = load float, float* %arrayidx3.3, align 4
232  %add.3 = add nsw i32 %X, 3
233  %arrayidx512.3 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %add.3
234  store float %i5, float addrspace(3)* %arrayidx512.3, align 4
235  %sub = add nsw i32 %X, -1
236  %arrayidx711 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %sub
237  %i6 = load float, float addrspace(3)* %arrayidx711, align 4
238  %idxprom8 = sext i32 %X to i64
239  %arrayidx9 = getelementptr inbounds float, float* %i1, i64 %idxprom8
240  store float %i6, float* %arrayidx9, align 4
241  ret void
242}
243
244; GCN-LABEL: global_ptr_arg_clobbered:
245; GCN: global_store_dwordx2
246; GCN: global_load_dwordx2
247; GCN: flat_load_dword
248; GCN: flat_store_dword
249define amdgpu_kernel void @global_ptr_arg_clobbered(float* addrspace(1)* nocapture readonly %Arg, i32 %X) {
250; CHECK-LABEL: @global_ptr_arg_clobbered(
251; CHECK-NEXT:  entry:
252; CHECK-NEXT:    [[I:%.*]] = tail call i32 @llvm.amdgcn.workitem.id.x()
253; CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[I]] to i64
254; CHECK-NEXT:    [[ARRAYIDX10:%.*]] = getelementptr inbounds float*, float* addrspace(1)* [[ARG:%.*]], i64 [[IDXPROM]]
255; CHECK-NEXT:    [[ARRAYIDX11:%.*]] = getelementptr inbounds float*, float* addrspace(1)* [[ARRAYIDX10]], i32 [[X:%.*]]
256; CHECK-NEXT:    store float* null, float* addrspace(1)* [[ARRAYIDX11]], align 4
257; CHECK-NEXT:    [[I1:%.*]] = load float*, float* addrspace(1)* [[ARRAYIDX10]], align 8
258; CHECK-NEXT:    [[I2:%.*]] = load float, float* [[I1]], align 4
259; CHECK-NEXT:    [[ARRAYIDX512:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[X]]
260; CHECK-NEXT:    store float [[I2]], float addrspace(3)* [[ARRAYIDX512]], align 4
261; CHECK-NEXT:    [[SUB:%.*]] = add nsw i32 [[X]], -1
262; CHECK-NEXT:    [[ARRAYIDX711:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[SUB]]
263; CHECK-NEXT:    [[I6:%.*]] = load float, float addrspace(3)* [[ARRAYIDX711]], align 4
264; CHECK-NEXT:    [[IDXPROM8:%.*]] = sext i32 [[X]] to i64
265; CHECK-NEXT:    [[ARRAYIDX9:%.*]] = getelementptr inbounds float, float* [[I1]], i64 [[IDXPROM8]]
266; CHECK-NEXT:    store float [[I6]], float* [[ARRAYIDX9]], align 4
267; CHECK-NEXT:    ret void
268;
269entry:
270  %i = tail call i32 @llvm.amdgcn.workitem.id.x()
271  %idxprom = zext i32 %i to i64
272  %arrayidx10 = getelementptr inbounds float*, float* addrspace(1)* %Arg, i64 %idxprom
273  %arrayidx11 = getelementptr inbounds float*, float* addrspace(1)* %arrayidx10, i32 %X
274  store float* null, float* addrspace(1)* %arrayidx11, align 4
275  %i1 = load float*, float* addrspace(1)* %arrayidx10, align 8
276  %i2 = load float, float* %i1, align 4
277  %arrayidx512 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %X
278  store float %i2, float addrspace(3)* %arrayidx512, align 4
279  %sub = add nsw i32 %X, -1
280  %arrayidx711 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %sub
281  %i6 = load float, float addrspace(3)* %arrayidx711, align 4
282  %idxprom8 = sext i32 %X to i64
283  %arrayidx9 = getelementptr inbounds float, float* %i1, i64 %idxprom8
284  store float %i6, float* %arrayidx9, align 4
285  ret void
286}
287
288; GCN-LABEL: global_ptr_arg_clobbered_after_load:
289; GCN: global_load_dwordx2
290; GCN: global_store_dwordx2
291; GCN: global_load_dword
292; GCN: global_store_dword
293define amdgpu_kernel void @global_ptr_arg_clobbered_after_load(float* addrspace(1)* nocapture readonly %Arg, i32 %X) {
294; CHECK-LABEL: @global_ptr_arg_clobbered_after_load(
295; CHECK-NEXT:  entry:
296; CHECK-NEXT:    [[I:%.*]] = tail call i32 @llvm.amdgcn.workitem.id.x()
297; CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[I]] to i64
298; CHECK-NEXT:    [[ARRAYIDX10:%.*]] = getelementptr inbounds float*, float* addrspace(1)* [[ARG:%.*]], i64 [[IDXPROM]]
299; CHECK-NEXT:    [[ARRAYIDX10_CONST:%.*]] = addrspacecast float* addrspace(1)* [[ARRAYIDX10]] to float* addrspace(4)*
300; CHECK-NEXT:    [[I1:%.*]] = load float*, float* addrspace(4)* [[ARRAYIDX10_CONST]], align 8
301; CHECK-NEXT:    [[TMP0:%.*]] = addrspacecast float* [[I1]] to float addrspace(1)*
302; CHECK-NEXT:    [[ARRAYIDX11:%.*]] = getelementptr inbounds float*, float* addrspace(1)* [[ARRAYIDX10]], i32 [[X:%.*]]
303; CHECK-NEXT:    store float* null, float* addrspace(1)* [[ARRAYIDX11]], align 4
304; CHECK-NEXT:    [[I2:%.*]] = load float, float addrspace(1)* [[TMP0]], align 4
305; CHECK-NEXT:    [[ARRAYIDX512:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[X]]
306; CHECK-NEXT:    store float [[I2]], float addrspace(3)* [[ARRAYIDX512]], align 4
307; CHECK-NEXT:    [[SUB:%.*]] = add nsw i32 [[X]], -1
308; CHECK-NEXT:    [[ARRAYIDX711:%.*]] = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 [[SUB]]
309; CHECK-NEXT:    [[I6:%.*]] = load float, float addrspace(3)* [[ARRAYIDX711]], align 4
310; CHECK-NEXT:    [[IDXPROM8:%.*]] = sext i32 [[X]] to i64
311; CHECK-NEXT:    [[ARRAYIDX9:%.*]] = getelementptr inbounds float, float addrspace(1)* [[TMP0]], i64 [[IDXPROM8]]
312; CHECK-NEXT:    store float [[I6]], float addrspace(1)* [[ARRAYIDX9]], align 4
313; CHECK-NEXT:    ret void
314;
315entry:
316  %i = tail call i32 @llvm.amdgcn.workitem.id.x()
317  %idxprom = zext i32 %i to i64
318  %arrayidx10 = getelementptr inbounds float*, float* addrspace(1)* %Arg, i64 %idxprom
319  %i1 = load float*, float* addrspace(1)* %arrayidx10, align 8
320  %arrayidx11 = getelementptr inbounds float*, float* addrspace(1)* %arrayidx10, i32 %X
321  store float* null, float* addrspace(1)* %arrayidx11, align 4
322  %i2 = load float, float* %i1, align 4
323  %arrayidx512 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %X
324  store float %i2, float addrspace(3)* %arrayidx512, align 4
325  %sub = add nsw i32 %X, -1
326  %arrayidx711 = getelementptr inbounds [4 x float], [4 x float] addrspace(3)* @LDS, i32 0, i32 %sub
327  %i6 = load float, float addrspace(3)* %arrayidx711, align 4
328  %idxprom8 = sext i32 %X to i64
329  %arrayidx9 = getelementptr inbounds float, float* %i1, i64 %idxprom8
330  store float %i6, float* %arrayidx9, align 4
331  ret void
332}
333
334; GCN-LABEL: ptr_nest_3_barrier:
335; GCN-COUNT-2: global_load_dwordx2
336; GCN:         global_store_dword
337define amdgpu_kernel void @ptr_nest_3_barrier(float** addrspace(1)* nocapture readonly %Arg) {
338; CHECK-LABEL: @ptr_nest_3_barrier(
339; CHECK-NEXT:  entry:
340; CHECK-NEXT:    [[I:%.*]] = tail call i32 @llvm.amdgcn.workitem.id.x()
341; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds float**, float** addrspace(1)* [[ARG:%.*]], i32 [[I]]
342; CHECK-NEXT:    tail call void @llvm.amdgcn.s.barrier()
343; CHECK-NEXT:    [[P1_CONST:%.*]] = addrspacecast float** addrspace(1)* [[P1]] to float** addrspace(4)*
344; CHECK-NEXT:    [[P2:%.*]] = load float**, float** addrspace(4)* [[P1_CONST]], align 8
345; CHECK-NEXT:    [[TMP0:%.*]] = addrspacecast float** [[P2]] to float* addrspace(1)*
346; CHECK-NEXT:    [[TMP1:%.*]] = addrspacecast float* addrspace(1)* [[TMP0]] to float**
347; CHECK-NEXT:    [[P2_FLAT:%.*]] = addrspacecast float* addrspace(1)* [[TMP0]] to float**
348; CHECK-NEXT:    [[P2_CONST:%.*]] = addrspacecast float** [[TMP1]] to float* addrspace(4)*
349; CHECK-NEXT:    [[P3:%.*]] = load float*, float* addrspace(4)* [[P2_CONST]], align 8
350; CHECK-NEXT:    [[TMP2:%.*]] = addrspacecast float* [[P3]] to float addrspace(1)*
351; CHECK-NEXT:    store float 0.000000e+00, float addrspace(1)* [[TMP2]], align 4
352; CHECK-NEXT:    ret void
353;
354entry:
355  %i = tail call i32 @llvm.amdgcn.workitem.id.x()
356  %p1 = getelementptr inbounds float**, float** addrspace(1)* %Arg, i32 %i
357  tail call void @llvm.amdgcn.s.barrier()
358  %p2 = load float**, float** addrspace(1)* %p1, align 8
359  %p3 = load float*, float** %p2, align 8
360  store float 0.000000e+00, float* %p3, align 4
361  ret void
362}
363
364; GCN-LABEL: flat_ptr_nest_2:
365; GCN: s_lshl_b64
366; GCN: s_load_dwordx2
367; GCN: global_store_dword
368define amdgpu_kernel void @flat_ptr_nest_2(float** nocapture readonly %Arg, i32 %i) {
369; CHECK-LABEL: @flat_ptr_nest_2(
370; CHECK-NEXT:  entry:
371; CHECK-NEXT:    [[ARG_GLOBAL:%.*]] = addrspacecast float** [[ARG:%.*]] to float* addrspace(1)*
372; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds float*, float* addrspace(1)* [[ARG_GLOBAL]], i32 [[I:%.*]]
373; CHECK-NEXT:    [[TMP0:%.*]] = addrspacecast float* addrspace(1)* [[P1]] to float**
374; CHECK-NEXT:    [[P1_CONST:%.*]] = addrspacecast float** [[TMP0]] to float* addrspace(4)*
375; CHECK-NEXT:    [[P2:%.*]] = load float*, float* addrspace(4)* [[P1_CONST]], align 8
376; CHECK-NEXT:    [[TMP1:%.*]] = addrspacecast float* [[P2]] to float addrspace(1)*
377; CHECK-NEXT:    store float 0.000000e+00, float addrspace(1)* [[TMP1]], align 4
378; CHECK-NEXT:    ret void
379;
380entry:
381  %p1 = getelementptr inbounds float*, float** %Arg, i32 %i
382  %p2 = load float*, float** %p1, align 8
383  store float 0.000000e+00, float* %p2, align 4
384  ret void
385}
386
387; GCN-LABEL: const_ptr_nest_3:
388; GCN: s_lshl_b64
389; GCN: s_load_dwordx2
390; GCN: s_load_dwordx2
391; GCN: global_store_dword
392define amdgpu_kernel void @const_ptr_nest_3(float* addrspace(4)* addrspace(4)* nocapture readonly %Arg, i32 %i) {
393; CHECK-LABEL: @const_ptr_nest_3(
394; CHECK-NEXT:  entry:
395; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds float* addrspace(4)*, float* addrspace(4)* addrspace(4)* [[ARG:%.*]], i32 [[I:%.*]]
396; CHECK-NEXT:    [[P2:%.*]] = load float* addrspace(4)*, float* addrspace(4)* addrspace(4)* [[P1]], align 8
397; CHECK-NEXT:    [[P3:%.*]] = load float*, float* addrspace(4)* [[P2]], align 8
398; CHECK-NEXT:    [[TMP0:%.*]] = addrspacecast float* [[P3]] to float addrspace(1)*
399; CHECK-NEXT:    store float 0.000000e+00, float addrspace(1)* [[TMP0]], align 4
400; CHECK-NEXT:    ret void
401;
402entry:
403  %p1 = getelementptr inbounds float* addrspace(4)*, float* addrspace(4)* addrspace(4)* %Arg, i32 %i
404  %p2 = load float* addrspace(4)*, float * addrspace(4)* addrspace(4)* %p1, align 8
405  %p3 = load float*, float* addrspace(4)* %p2, align 8
406  store float 0.000000e+00, float* %p3, align 4
407  ret void
408}
409
410; GCN-LABEL: cast_from_const_const_ptr_nest_3:
411; GCN: s_lshl_b64
412; GCN: s_load_dwordx2
413; GCN: s_load_dwordx2
414; GCN: global_store_dword
415define amdgpu_kernel void @cast_from_const_const_ptr_nest_3(float* addrspace(4)* addrspace(4)* nocapture readonly %Arg, i32 %i) {
416; CHECK-LABEL: @cast_from_const_const_ptr_nest_3(
417; CHECK-NEXT:  entry:
418; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds float* addrspace(4)*, float* addrspace(4)* addrspace(4)* [[ARG:%.*]], i32 [[I:%.*]]
419; CHECK-NEXT:    [[P2:%.*]] = load float* addrspace(4)*, float* addrspace(4)* addrspace(4)* [[P1]], align 8
420; CHECK-NEXT:    [[P3:%.*]] = load float*, float* addrspace(4)* [[P2]], align 8
421; CHECK-NEXT:    [[P3_GLOBAL:%.*]] = addrspacecast float* [[P3]] to float addrspace(1)*
422; CHECK-NEXT:    store float 0.000000e+00, float addrspace(1)* [[P3_GLOBAL]], align 4
423; CHECK-NEXT:    ret void
424;
425entry:
426  %p1 = getelementptr inbounds float* addrspace(4)*, float* addrspace(4)* addrspace(4)* %Arg, i32 %i
427  %a1 = addrspacecast float* addrspace(4)* addrspace(4)* %p1 to float* addrspace(4)**
428  %p2 = load float* addrspace(4)*, float* addrspace(4)** %a1, align 8
429  %a2 = addrspacecast float* addrspace(4)* %p2 to float**
430  %p3 = load float*, float** %a2, align 8
431  store float 0.000000e+00, float* %p3, align 4
432  ret void
433}
434
435; GCN-LABEL: flat_ptr_volatile_load:
436; GCN: s_lshl_b64
437; GCN: flat_load_dwordx2
438; GCN: global_store_dword
439define amdgpu_kernel void @flat_ptr_volatile_load(float** nocapture readonly %Arg, i32 %i) {
440; CHECK-LABEL: @flat_ptr_volatile_load(
441; CHECK-NEXT:  entry:
442; CHECK-NEXT:    [[ARG_GLOBAL:%.*]] = addrspacecast float** [[ARG:%.*]] to float* addrspace(1)*
443; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds float*, float* addrspace(1)* [[ARG_GLOBAL]], i32 [[I:%.*]]
444; CHECK-NEXT:    [[TMP0:%.*]] = addrspacecast float* addrspace(1)* [[P1]] to float**
445; CHECK-NEXT:    [[P2:%.*]] = load volatile float*, float** [[TMP0]], align 8
446; CHECK-NEXT:    [[P2_GLOBAL:%.*]] = addrspacecast float* [[P2]] to float addrspace(1)*
447; CHECK-NEXT:    store float 0.000000e+00, float addrspace(1)* [[P2_GLOBAL]], align 4
448; CHECK-NEXT:    ret void
449;
450entry:
451  %p1 = getelementptr inbounds float*, float** %Arg, i32 %i
452  %p2 = load volatile float*, float** %p1, align 8
453  store float 0.000000e+00, float* %p2, align 4
454  ret void
455}
456
457; GCN-LABEL: flat_ptr_atomic_load:
458; GCN: s_lshl_b64
459; GCN: global_load_dwordx2
460; GCN: global_store_dword
461define amdgpu_kernel void @flat_ptr_atomic_load(float** nocapture readonly %Arg, i32 %i) {
462; CHECK-LABEL: @flat_ptr_atomic_load(
463; CHECK-NEXT:  entry:
464; CHECK-NEXT:    [[ARG_GLOBAL:%.*]] = addrspacecast float** [[ARG:%.*]] to float* addrspace(1)*
465; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds float*, float* addrspace(1)* [[ARG_GLOBAL]], i32 [[I:%.*]]
466; CHECK-NEXT:    [[P2:%.*]] = load atomic float*, float* addrspace(1)* [[P1]] monotonic, align 8
467; CHECK-NEXT:    [[P2_GLOBAL:%.*]] = addrspacecast float* [[P2]] to float addrspace(1)*
468; CHECK-NEXT:    store float 0.000000e+00, float addrspace(1)* [[P2_GLOBAL]], align 4
469; CHECK-NEXT:    ret void
470;
471entry:
472  %p1 = getelementptr inbounds float*, float** %Arg, i32 %i
473  %p2 = load atomic float*, float** %p1 monotonic, align 8
474  store float 0.000000e+00, float* %p2, align 4
475  ret void
476}
477
478; GCN-LABEL: cast_changing_pointee_type:
479; GCN: s_lshl_b64
480; GCN: s_load_dwordx2
481; GCN: s_load_dwordx2
482; GCN: global_store_dword
483define amdgpu_kernel void @cast_changing_pointee_type(float* addrspace(1)* addrspace(1)* nocapture readonly %Arg, i32 %i) {
484; CHECK-LABEL: @cast_changing_pointee_type(
485; CHECK-NEXT:  entry:
486; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds float* addrspace(1)*, float* addrspace(1)* addrspace(1)* [[ARG:%.*]], i32 [[I:%.*]]
487; CHECK-NEXT:    [[A1:%.*]] = bitcast float* addrspace(1)* addrspace(1)* [[P1]] to i32* addrspace(1)* addrspace(1)*
488; CHECK-NEXT:    [[TMP0:%.*]] = addrspacecast float* addrspace(1)* addrspace(1)* [[P1]] to i32* addrspace(1)**
489; CHECK-NEXT:    [[A1_CONST:%.*]] = addrspacecast i32* addrspace(1)** [[TMP0]] to i32* addrspace(1)* addrspace(4)*
490; CHECK-NEXT:    [[P2:%.*]] = load i32* addrspace(1)*, i32* addrspace(1)* addrspace(4)* [[A1_CONST]], align 8
491; CHECK-NEXT:    [[A2:%.*]] = bitcast i32* addrspace(1)* [[P2]] to float* addrspace(1)*
492; CHECK-NEXT:    [[TMP1:%.*]] = addrspacecast i32* addrspace(1)* [[P2]] to float**
493; CHECK-NEXT:    [[A2_CONST:%.*]] = addrspacecast float** [[TMP1]] to float* addrspace(4)*
494; CHECK-NEXT:    [[P3:%.*]] = load float*, float* addrspace(4)* [[A2_CONST]], align 8
495; CHECK-NEXT:    [[TMP2:%.*]] = addrspacecast float* [[P3]] to float addrspace(1)*
496; CHECK-NEXT:    store float 0.000000e+00, float addrspace(1)* [[TMP2]], align 4
497; CHECK-NEXT:    ret void
498;
499entry:
500  %p1 = getelementptr inbounds float* addrspace(1)*, float* addrspace(1)* addrspace(1)* %Arg, i32 %i
501  %a1 = addrspacecast float* addrspace(1)* addrspace(1)* %p1 to i32* addrspace(1)**
502  %p2 = load i32* addrspace(1)*, i32* addrspace(1)** %a1, align 8
503  %a2 = addrspacecast i32* addrspace(1)* %p2 to float**
504  %p3 = load float*, float** %a2, align 8
505  store float 0.000000e+00, float* %p3, align 4
506  ret void
507}
508
509declare i32 @llvm.amdgcn.workitem.id.x()
510declare void @llvm.amdgcn.s.barrier()
511