1; Verifies correctness of load/store of parameters and return values.
2; RUN: llc < %s -march=nvptx64 -mcpu=sm_35 -O0 -verify-machineinstrs | FileCheck -allow-deprecated-dag-overlap %s
3; RUN: %if ptxas %{ llc < %s -march=nvptx64 -mcpu=sm_35 -O0 -verify-machineinstrs | %ptxas-verify -arch=sm_35 %}
4
5%s_i1 = type { i1 }
6%s_i8 = type { i8 }
7%s_i16 = type { i16 }
8%s_f16 = type { half }
9%s_i32 = type { i32 }
10%s_f32 = type { float }
11%s_i64 = type { i64 }
12%s_f64 = type { double }
13
14; More complicated types. i64 is used to increase natural alignment
15; requirement for the type.
16%s_i32x4 = type { i32, i32, i32, i32, i64}
17%s_i32f32 = type { i32, float, i32, float, i64}
18%s_i8i32x4 = type { i32, i32, i8, i32, i32, i64}
19%s_i8i32x4p = type <{ i32, i32, i8, i32, i32, i64}>
20%s_crossfield = type { i32, [2 x i32], <4 x i32>, [3 x {i32, i32, i32}]}
21; All scalar parameters must be at least 32 bits in size.
22; i1 is loaded/stored as i8.
23
24; CHECK: .func  (.param .b32 func_retval0)
25; CHECK-LABEL: test_i1(
26; CHECK-NEXT: .param .b32 test_i1_param_0
27; CHECK:      ld.param.u8 [[A8:%rs[0-9]+]], [test_i1_param_0];
28; CHECK:      and.b16 [[A:%rs[0-9]+]], [[A8]], 1;
29; CHECK:      setp.eq.b16 %p1, [[A]], 1
30; CHECK:      cvt.u32.u16 [[B:%r[0-9]+]], [[A8]]
31; CHECK:      and.b32 [[C:%r[0-9]+]], [[B]], 1;
32; CHECK:      .param .b32 param0;
33; CHECK:      st.param.b32    [param0+0], [[C]]
34; CHECK:      .param .b32 retval0;
35; CHECK:      call.uni
36; CHECK-NEXT: test_i1,
37; CHECK:      ld.param.b32    [[R8:%r[0-9]+]], [retval0+0];
38; CHECK:      and.b32         [[R:%r[0-9]+]], [[R8]], 1;
39; CHECK:      st.param.b32    [func_retval0+0], [[R]];
40; CHECK:      ret;
41define i1 @test_i1(i1 %a) {
42  %r = tail call i1 @test_i1(i1 %a);
43  ret i1 %r;
44}
45
46; Signed i1 is a somewhat special case. We only care about one bit and
47; then us neg.s32 to convert it to 32-bit -1 if it's set.
48; CHECK: .func  (.param .b32 func_retval0)
49; CHECK-LABEL: test_i1s(
50; CHECK-NEXT: .param .b32 test_i1s_param_0
51; CHECK:      ld.param.u8 [[A8:%rs[0-9]+]], [test_i1s_param_0];
52; CHECK:      cvt.u32.u16     [[A32:%r[0-9]+]], [[A8]];
53; CHECK:      and.b32         [[A1:%r[0-9]+]], [[A32]], 1;
54; CHECK:      neg.s32         [[A:%r[0-9]+]], [[A1]];
55; CHECK:      .param .b32 param0;
56; CHECK:      st.param.b32    [param0+0], [[A]];
57; CHECK:      .param .b32 retval0;
58; CHECK:      call.uni
59; CHECK:      ld.param.b32    [[R8:%r[0-9]+]], [retval0+0];
60; CHECK:      and.b32         [[R1:%r[0-9]+]], [[R8]], 1;
61; CHECK:      neg.s32         [[R:%r[0-9]+]], [[R1]];
62; CHECK:      st.param.b32    [func_retval0+0], [[R]];
63; CHECK-NEXT: ret;
64define signext i1 @test_i1s(i1 signext %a) {
65       %r = tail call signext i1 @test_i1s(i1 signext %a);
66       ret i1 %r;
67}
68
69; Make sure that i1 loads are vectorized as i8 loads, respecting each element alignment.
70; CHECK: .func  (.param .align 1 .b8 func_retval0[1])
71; CHECK-LABEL: test_v3i1(
72; CHECK-NEXT: .param .align 1 .b8 test_v3i1_param_0[1]
73; CHECK-DAG:  ld.param.u8     [[E2:%rs[0-9]+]], [test_v3i1_param_0+2];
74; CHECK-DAG:  ld.param.u8     [[E0:%rs[0-9]+]], [test_v3i1_param_0]
75; CHECK:      .param .align 1 .b8 param0[1];
76; CHECK-DAG:  st.param.b8     [param0+0], [[E0]];
77; CHECK-DAG:  st.param.b8     [param0+2], [[E2]];
78; CHECK:      .param .align 1 .b8 retval0[1];
79; CHECK:      call.uni (retval0),
80; CHECK-NEXT: test_v3i1,
81; CHECK-DAG:  ld.param.b8     [[RE0:%rs[0-9]+]], [retval0+0];
82; CHECK-DAG:  ld.param.b8     [[RE2:%rs[0-9]+]], [retval0+2];
83; CHECK-DAG:  st.param.b8     [func_retval0+0], [[RE0]]
84; CHECK-DAG:  st.param.b8     [func_retval0+2], [[RE2]];
85; CHECK-NEXT: ret;
86define <3 x i1> @test_v3i1(<3 x i1> %a) {
87       %r = tail call <3 x i1> @test_v3i1(<3 x i1> %a);
88       ret <3 x i1> %r;
89}
90
91; CHECK: .func  (.param .align 1 .b8 func_retval0[1])
92; CHECK-LABEL: test_v4i1(
93; CHECK-NEXT: .param .align 1 .b8 test_v4i1_param_0[1]
94; CHECK:      ld.param.u8 [[E0:%rs[0-9]+]], [test_v4i1_param_0]
95; CHECK:      .param .align 1 .b8 param0[1];
96; CHECK:      st.param.b8  [param0+0], [[E0]];
97; CHECK:      .param .align 1 .b8 retval0[1];
98; CHECK:      call.uni (retval0),
99; CHECK:      test_v4i1,
100; CHECK:      ld.param.b8  [[RE0:%rs[0-9]+]], [retval0+0];
101; CHECK:      ld.param.b8  [[RE1:%rs[0-9]+]], [retval0+1];
102; CHECK:      ld.param.b8  [[RE2:%rs[0-9]+]], [retval0+2];
103; CHECK:      ld.param.b8  [[RE3:%rs[0-9]+]], [retval0+3];
104; CHECK:      st.param.b8  [func_retval0+0], [[RE0]];
105; CHECK:      st.param.b8  [func_retval0+1], [[RE1]];
106; CHECK:      st.param.b8  [func_retval0+2], [[RE2]];
107; CHECK:      st.param.b8  [func_retval0+3], [[RE3]];
108; CHECK-NEXT: ret;
109define <4 x i1> @test_v4i1(<4 x i1> %a) {
110       %r = tail call <4 x i1> @test_v4i1(<4 x i1> %a);
111       ret <4 x i1> %r;
112}
113
114; CHECK: .func  (.param .align 1 .b8 func_retval0[1])
115; CHECK-LABEL: test_v5i1(
116; CHECK-NEXT: .param .align 1 .b8 test_v5i1_param_0[1]
117; CHECK-DAG:  ld.param.u8     [[E4:%rs[0-9]+]], [test_v5i1_param_0+4];
118; CHECK-DAG:  ld.param.u8     [[E0:%rs[0-9]+]], [test_v5i1_param_0]
119; CHECK:      .param .align 1 .b8 param0[1];
120; CHECK-DAG:  st.param.b8     [param0+0], [[E0]];
121; CHECK-DAG:  st.param.b8     [param0+4], [[E4]];
122; CHECK:      .param .align 1 .b8 retval0[1];
123; CHECK:      call.uni (retval0),
124; CHECK-NEXT: test_v5i1,
125; CHECK-DAG:  ld.param.b8  [[RE0:%rs[0-9]+]], [retval0+0];
126; CHECK-DAG:  ld.param.b8     [[RE4:%rs[0-9]+]], [retval0+4];
127; CHECK-DAG:  st.param.b8  [func_retval0+0], [[RE0]]
128; CHECK-DAG:  st.param.b8     [func_retval0+4], [[RE4]];
129; CHECK-NEXT: ret;
130define <5 x i1> @test_v5i1(<5 x i1> %a) {
131       %r = tail call <5 x i1> @test_v5i1(<5 x i1> %a);
132       ret <5 x i1> %r;
133}
134
135; Unsigned i8 is loaded directly into 32-bit register.
136; CHECK: .func  (.param .b32 func_retval0)
137; CHECK-LABEL: test_i8(
138; CHECK-NEXT: .param .b32 test_i8_param_0
139; CHECK:      ld.param.u8 [[A8:%rs[0-9]+]], [test_i8_param_0];
140; CHECK:      cvt.u32.u16     [[A32:%r[0-9]+]], [[A8]];
141; CHECK:      and.b32         [[A:%r[0-9]+]], [[A32]], 255;
142; CHECK:      .param .b32 param0;
143; CHECK:      st.param.b32    [param0+0], [[A]];
144; CHECK:      .param .b32 retval0;
145; CHECK:      call.uni (retval0),
146; CHECK:      test_i8,
147; CHECK:      ld.param.b32    [[R32:%r[0-9]+]], [retval0+0];
148; CHECK:      and.b32         [[R:%r[0-9]+]], [[R32]], 255;
149; CHECK:      st.param.b32    [func_retval0+0], [[R]];
150; CHECK-NEXT: ret;
151define i8 @test_i8(i8 %a) {
152       %r = tail call i8 @test_i8(i8 %a);
153       ret i8 %r;
154}
155
156; signed i8 is loaded into 16-bit register which is then sign-extended to i32.
157; CHECK: .func  (.param .b32 func_retval0)
158; CHECK-LABEL: test_i8s(
159; CHECK-NEXT: .param .b32 test_i8s_param_0
160; CHECK:      ld.param.s8 [[A8:%rs[0-9]+]], [test_i8s_param_0];
161; CHECK:      cvt.s32.s16     [[A:%r[0-9]+]], [[A8]];
162; CHECK:      .param .b32 param0;
163; CHECK:      st.param.b32    [param0+0], [[A]];
164; CHECK:      .param .b32 retval0;
165; CHECK:      call.uni (retval0),
166; CHECK:      test_i8s,
167; CHECK:      ld.param.b32    [[R32:%r[0-9]+]], [retval0+0];
168; -- This is suspicious (though correct) -- why not cvt.u8.u32, cvt.s8.s32 ?
169; CHECK:      cvt.u16.u32     [[R16:%rs[0-9]+]], [[R32]];
170; CHECK:      cvt.s32.s16     [[R:%r[0-9]+]], [[R16]];
171; CHECK:      st.param.b32    [func_retval0+0], [[R]];
172; CHECK-NEXT: ret;
173define signext i8 @test_i8s(i8 signext %a) {
174       %r = tail call signext i8 @test_i8s(i8 signext %a);
175       ret i8 %r;
176}
177
178; CHECK: .func  (.param .align 4 .b8 func_retval0[4])
179; CHECK-LABEL: test_v3i8(
180; CHECK-NEXT: .param .align 4 .b8 test_v3i8_param_0[4]
181; CHECK-DAG:  ld.param.u8     [[E2:%rs[0-9]+]], [test_v3i8_param_0+2];
182; CHECK-DAG:  ld.param.v2.u8  {[[E0:%rs[0-9]+]], [[E1:%rs[0-9]+]]}, [test_v3i8_param_0];
183; CHECK:      .param .align 4 .b8 param0[4];
184; CHECK:      st.param.v2.b8  [param0+0], {[[E0]], [[E1]]};
185; CHECK:      st.param.b8     [param0+2], [[E2]];
186; CHECK:      .param .align 4 .b8 retval0[4];
187; CHECK:      call.uni (retval0),
188; CHECK-NEXT: test_v3i8,
189; CHECK-DAG:  ld.param.v2.b8  {[[RE0:%rs[0-9]+]], [[RE1:%rs[0-9]+]]}, [retval0+0];
190; CHECK-DAG:  ld.param.b8     [[RE2:%rs[0-9]+]], [retval0+2];
191; CHECK-DAG:  st.param.v2.b8  [func_retval0+0], {[[RE0]], [[RE1]]};
192; CHECK-DAG:  st.param.b8     [func_retval0+2], [[RE2]];
193; CHECK-NEXT: ret;
194define <3 x i8> @test_v3i8(<3 x i8> %a) {
195       %r = tail call <3 x i8> @test_v3i8(<3 x i8> %a);
196       ret <3 x i8> %r;
197}
198
199; CHECK: .func  (.param .align 4 .b8 func_retval0[4])
200; CHECK-LABEL: test_v4i8(
201; CHECK-NEXT: .param .align 4 .b8 test_v4i8_param_0[4]
202; CHECK:      ld.param.v4.u8 {[[E0:%rs[0-9]+]], [[E1:%rs[0-9]+]], [[E2:%rs[0-9]+]], [[E3:%rs[0-9]+]]}, [test_v4i8_param_0]
203; CHECK:      .param .align 4 .b8 param0[4];
204; CHECK:      st.param.v4.b8  [param0+0], {[[E0]], [[E1]], [[E2]], [[E3]]};
205; CHECK:      .param .align 4 .b8 retval0[4];
206; CHECK:      call.uni (retval0),
207; CHECK-NEXT: test_v4i8,
208; CHECK:      ld.param.v4.b8  {[[RE0:%rs[0-9]+]], [[RE1:%rs[0-9]+]], [[RE2:%rs[0-9]+]], [[RE3:%rs[0-9]+]]}, [retval0+0];
209; CHECK:      st.param.v4.b8 [func_retval0+0], {[[RE0]], [[RE1]], [[RE2]], [[RE3]]}
210; CHECK-NEXT: ret;
211define <4 x i8> @test_v4i8(<4 x i8> %a) {
212       %r = tail call <4 x i8> @test_v4i8(<4 x i8> %a);
213       ret <4 x i8> %r;
214}
215
216; CHECK: .func  (.param .align 8 .b8 func_retval0[8])
217; CHECK-LABEL: test_v5i8(
218; CHECK-NEXT: .param .align 8 .b8 test_v5i8_param_0[8]
219; CHECK-DAG:  ld.param.u8     [[E4:%rs[0-9]+]], [test_v5i8_param_0+4];
220; CHECK-DAG:  ld.param.v4.u8  {[[E0:%rs[0-9]+]], [[E1:%rs[0-9]+]], [[E2:%rs[0-9]+]], [[E3:%rs[0-9]+]]}, [test_v5i8_param_0]
221; CHECK:      .param .align 8 .b8 param0[8];
222; CHECK-DAG:  st.param.v4.b8  [param0+0], {[[E0]], [[E1]], [[E2]], [[E3]]};
223; CHECK-DAG:  st.param.b8     [param0+4], [[E4]];
224; CHECK:      .param .align 8 .b8 retval0[8];
225; CHECK:      call.uni (retval0),
226; CHECK-NEXT: test_v5i8,
227; CHECK-DAG:  ld.param.v4.b8  {[[RE0:%rs[0-9]+]], [[RE1:%rs[0-9]+]], [[RE2:%rs[0-9]+]], [[RE3:%rs[0-9]+]]}, [retval0+0];
228; CHECK-DAG:  ld.param.b8     [[RE4:%rs[0-9]+]], [retval0+4];
229; CHECK-DAG:  st.param.v4.b8  [func_retval0+0], {[[RE0]], [[RE1]], [[RE2]], [[RE3]]}
230; CHECK-DAG:  st.param.b8     [func_retval0+4], [[RE4]];
231; CHECK-NEXT: ret;
232define <5 x i8> @test_v5i8(<5 x i8> %a) {
233       %r = tail call <5 x i8> @test_v5i8(<5 x i8> %a);
234       ret <5 x i8> %r;
235}
236
237; CHECK: .func  (.param .b32 func_retval0)
238; CHECK-LABEL: test_i16(
239; CHECK-NEXT: .param .b32 test_i16_param_0
240; CHECK:      ld.param.u16    [[E16:%rs[0-9]+]], [test_i16_param_0];
241; CHECK:      cvt.u32.u16     [[E32:%r[0-9]+]], [[E16]];
242; CHECK:      .param .b32 param0;
243; CHECK:      st.param.b32    [param0+0], [[E32]];
244; CHECK:      .param .b32 retval0;
245; CHECK:      call.uni (retval0),
246; CHECK-NEXT: test_i16,
247; CHECK:      ld.param.b32    [[RE32:%r[0-9]+]], [retval0+0];
248; CHECK:      and.b32         [[R:%r[0-9]+]], [[RE32]], 65535;
249; CHECK:      st.param.b32    [func_retval0+0], [[R]];
250; CHECK-NEXT: ret;
251define i16 @test_i16(i16 %a) {
252       %r = tail call i16 @test_i16(i16 %a);
253       ret i16 %r;
254}
255
256; CHECK: .func  (.param .b32 func_retval0)
257; CHECK-LABEL: test_i16s(
258; CHECK-NEXT: .param .b32 test_i16s_param_0
259; CHECK:      ld.param.u16    [[E16:%rs[0-9]+]], [test_i16s_param_0];
260; CHECK:      cvt.s32.s16     [[E32:%r[0-9]+]], [[E16]];
261; CHECK:      .param .b32 param0;
262; CHECK:      st.param.b32    [param0+0], [[E32]];
263; CHECK:      .param .b32 retval0;
264; CHECK:      call.uni (retval0),
265; CHECK-NEXT: test_i16s,
266; CHECK:      ld.param.b32    [[RE32:%r[0-9]+]], [retval0+0];
267; CHECK:      cvt.s32.s16     [[R:%r[0-9]+]], [[RE32]];
268; CHECK:      st.param.b32    [func_retval0+0], [[R]];
269; CHECK-NEXT: ret;
270define signext i16 @test_i16s(i16 signext %a) {
271       %r = tail call signext i16 @test_i16s(i16 signext %a);
272       ret i16 %r;
273}
274
275; CHECK: .func  (.param .align 8 .b8 func_retval0[8])
276; CHECK-LABEL: test_v3i16(
277; CHECK-NEXT: .param .align 8 .b8 test_v3i16_param_0[8]
278; CHECK-DAG:  ld.param.u16    [[E2:%rs[0-9]+]], [test_v3i16_param_0+4];
279; CHECK-DAG:  ld.param.v2.u16 {[[E0:%rs[0-9]+]], [[E1:%rs[0-9]+]]}, [test_v3i16_param_0];
280; CHECK:      .param .align 8 .b8 param0[8];
281; CHECK:      st.param.v2.b16 [param0+0], {[[E0]], [[E1]]};
282; CHECK:      st.param.b16    [param0+4], [[E2]];
283; CHECK:      .param .align 8 .b8 retval0[8];
284; CHECK:      call.uni (retval0),
285; CHECK-NEXT: test_v3i16,
286; CHECK:      ld.param.v2.b16 {[[RE0:%rs[0-9]+]], [[RE1:%rs[0-9]+]]}, [retval0+0];
287; CHECK:      ld.param.b16    [[RE2:%rs[0-9]+]], [retval0+4];
288; CHECK-DAG:  st.param.v2.b16 [func_retval0+0], {[[RE0]], [[RE1]]};
289; CHECK-DAG:  st.param.b16    [func_retval0+4], [[RE2]];
290; CHECK-NEXT: ret;
291define <3 x i16> @test_v3i16(<3 x i16> %a) {
292       %r = tail call <3 x i16> @test_v3i16(<3 x i16> %a);
293       ret <3 x i16> %r;
294}
295
296; CHECK: .func  (.param .align 8 .b8 func_retval0[8])
297; CHECK-LABEL: test_v4i16(
298; CHECK-NEXT: .param .align 8 .b8 test_v4i16_param_0[8]
299; CHECK:      ld.param.v4.u16 {[[E0:%rs[0-9]+]], [[E1:%rs[0-9]+]], [[E2:%rs[0-9]+]], [[E3:%rs[0-9]+]]}, [test_v4i16_param_0]
300; CHECK:      .param .align 8 .b8 param0[8];
301; CHECK:      st.param.v4.b16 [param0+0], {[[E0]], [[E1]], [[E2]], [[E3]]};
302; CHECK:      .param .align 8 .b8 retval0[8];
303; CHECK:      call.uni (retval0),
304; CHECK-NEXT: test_v4i16,
305; CHECK:      ld.param.v4.b16 {[[RE0:%rs[0-9]+]], [[RE1:%rs[0-9]+]], [[RE2:%rs[0-9]+]], [[RE3:%rs[0-9]+]]}, [retval0+0];
306; CHECK:      st.param.v4.b16 [func_retval0+0], {[[RE0]], [[RE1]], [[RE2]], [[RE3]]}
307; CHECK-NEXT: ret;
308define <4 x i16> @test_v4i16(<4 x i16> %a) {
309       %r = tail call <4 x i16> @test_v4i16(<4 x i16> %a);
310       ret <4 x i16> %r;
311}
312
313; CHECK: .func  (.param .align 16 .b8 func_retval0[16])
314; CHECK-LABEL: test_v5i16(
315; CHECK-NEXT: .param .align 16 .b8 test_v5i16_param_0[16]
316; CHECK-DAG:  ld.param.u16    [[E4:%rs[0-9]+]], [test_v5i16_param_0+8];
317; CHECK-DAG:  ld.param.v4.u16 {[[E0:%rs[0-9]+]], [[E1:%rs[0-9]+]], [[E2:%rs[0-9]+]], [[E3:%rs[0-9]+]]}, [test_v5i16_param_0]
318; CHECK:      .param .align 16 .b8 param0[16];
319; CHECK-DAG:  st.param.v4.b16 [param0+0], {[[E0]], [[E1]], [[E2]], [[E3]]};
320; CHECK-DAG:  st.param.b16    [param0+8], [[E4]];
321; CHECK:      .param .align 16 .b8 retval0[16];
322; CHECK:      call.uni (retval0),
323; CHECK-NEXT: test_v5i16,
324; CHECK-DAG:  ld.param.v4.b16 {[[RE0:%rs[0-9]+]], [[RE1:%rs[0-9]+]], [[RE2:%rs[0-9]+]], [[RE3:%rs[0-9]+]]}, [retval0+0];
325; CHECK-DAG:  ld.param.b16    [[RE4:%rs[0-9]+]], [retval0+8];
326; CHECK-DAG:  st.param.v4.b16 [func_retval0+0], {[[RE0]], [[RE1]], [[RE2]], [[RE3]]}
327; CHECK-DAG:  st.param.b16    [func_retval0+8], [[RE4]];
328; CHECK-NEXT: ret;
329define <5 x i16> @test_v5i16(<5 x i16> %a) {
330       %r = tail call <5 x i16> @test_v5i16(<5 x i16> %a);
331       ret <5 x i16> %r;
332}
333
334; CHECK: .func  (.param .b32 func_retval0)
335; CHECK-LABEL: test_f16(
336; CHECK-NEXT: .param .b32 test_f16_param_0
337; CHECK:      ld.param.b16    [[E:%h[0-9]+]], [test_f16_param_0];
338; CHECK:      .param .b32 param0;
339; CHECK:      st.param.b16    [param0+0], [[E]];
340; CHECK:      .param .b32 retval0;
341; CHECK:      call.uni (retval0),
342; CHECK-NEXT: test_f16,
343; CHECK:      ld.param.b16    [[R:%h[0-9]+]], [retval0+0];
344; CHECK:      st.param.b16    [func_retval0+0], [[R]]
345; CHECK-NEXT: ret;
346define half @test_f16(half %a) {
347       %r = tail call half @test_f16(half %a);
348       ret half %r;
349}
350
351; CHECK: .func  (.param .align 4 .b8 func_retval0[4])
352; CHECK-LABEL: test_v2f16(
353; CHECK-NEXT: .param .align 4 .b8 test_v2f16_param_0[4]
354; CHECK:      ld.param.b32    [[E:%hh[0-9]+]], [test_v2f16_param_0];
355; CHECK:      .param .align 4 .b8 param0[4];
356; CHECK:      st.param.b32    [param0+0], [[E]];
357; CHECK:      .param .align 4 .b8 retval0[4];
358; CHECK:      call.uni (retval0),
359; CHECK-NEXT: test_v2f16,
360; CHECK:      ld.param.b32    [[R:%hh[0-9]+]], [retval0+0];
361; CHECK:      st.param.b32    [func_retval0+0], [[R]]
362; CHECK-NEXT: ret;
363define <2 x half> @test_v2f16(<2 x half> %a) {
364       %r = tail call <2 x half> @test_v2f16(<2 x half> %a);
365       ret <2 x half> %r;
366}
367
368; CHECK:.func  (.param .align 8 .b8 func_retval0[8])
369; CHECK-LABEL: test_v3f16(
370; CHECK:      .param .align 8 .b8 test_v3f16_param_0[8]
371; CHECK-DAG:  ld.param.b32    [[HH01:%hh[0-9]+]], [test_v3f16_param_0];
372; CHECK-DAG:  mov.b32         {[[E0:%h[0-9]+]], [[E1:%h[0-9]+]]}, [[HH01]];
373; CHECK-DAG:  ld.param.b16    [[E2:%h[0-9]+]], [test_v3f16_param_0+4];
374; CHECK:      .param .align 8 .b8 param0[8];
375; CHECK-DAG:  st.param.v2.b16 [param0+0], {[[E0]], [[E1]]};
376; CHECK-DAG:  st.param.b16    [param0+4], [[E2]];
377; CHECK:      .param .align 8 .b8 retval0[8];
378; CHECK:      call.uni (retval0),
379; CHECK:      test_v3f16,
380; CHECK-DAG:  ld.param.v2.b16 {[[R0:%h[0-9]+]], [[R1:%h[0-9]+]]}, [retval0+0];
381; CHECK-DAG:  ld.param.b16    [[R2:%h[0-9]+]], [retval0+4];
382; CHECK-DAG:  st.param.v2.b16 [func_retval0+0], {[[R0]], [[R1]]};
383; CHECK-DAG:  st.param.b16    [func_retval0+4], [[R2]];
384; CHECK:      ret;
385define <3 x half> @test_v3f16(<3 x half> %a) {
386       %r = tail call <3 x half> @test_v3f16(<3 x half> %a);
387       ret <3 x half> %r;
388}
389
390; CHECK:.func  (.param .align 8 .b8 func_retval0[8])
391; CHECK-LABEL: test_v4f16(
392; CHECK:      .param .align 8 .b8 test_v4f16_param_0[8]
393; CHECK:      ld.param.v2.u32 {[[R01:%r[0-9]+]], [[R23:%r[0-9]+]]}, [test_v4f16_param_0];
394; CHECK-DAG:  mov.b32         [[HH01:%hh[0-9]+]], [[R01]];
395; CHECK-DAG:  mov.b32         [[HH23:%hh[0-9]+]], [[R23]];
396; CHECK:      .param .align 8 .b8 param0[8];
397; CHECK:      st.param.v2.b32 [param0+0], {[[HH01]], [[HH23]]};
398; CHECK:      .param .align 8 .b8 retval0[8];
399; CHECK:      call.uni (retval0),
400; CHECK:      test_v4f16,
401; CHECK:      ld.param.v2.b32 {[[RH01:%hh[0-9]+]], [[RH23:%hh[0-9]+]]}, [retval0+0];
402; CHECK:      st.param.v2.b32 [func_retval0+0], {[[RH01]], [[RH23]]};
403; CHECK:      ret;
404define <4 x half> @test_v4f16(<4 x half> %a) {
405       %r = tail call <4 x half> @test_v4f16(<4 x half> %a);
406       ret <4 x half> %r;
407}
408
409; CHECK:.func  (.param .align 16 .b8 func_retval0[16])
410; CHECK-LABEL: test_v5f16(
411; CHECK:      .param .align 16 .b8 test_v5f16_param_0[16]
412; CHECK-DAG:  ld.param.v4.b16  {[[E0:%h[0-9]+]], [[E1:%h[0-9]+]], [[E2:%h[0-9]+]], [[E3:%h[0-9]+]]}, [test_v5f16_param_0];
413; CHECK-DAG:  mov.b32         {[[E0:%h[0-9]+]], [[E1:%h[0-9]+]]}, [[HH01]];
414; CHECK-DAG:  ld.param.b16    [[E4:%h[0-9]+]], [test_v5f16_param_0+8];
415; CHECK:      .param .align 16 .b8 param0[16];
416; CHECK-DAG:  st.param.v4.b16 [param0+0],
417; CHECK-DAG:  st.param.b16    [param0+8], [[E4]];
418; CHECK:      .param .align 16 .b8 retval0[16];
419; CHECK:      call.uni (retval0),
420; CHECK:      test_v5f16,
421; CHECK-DAG:  ld.param.v4.b16 {[[R0:%h[0-9]+]], [[R1:%h[0-9]+]], [[R2:%h[0-9]+]], [[R3:%h[0-9]+]]}, [retval0+0];
422; CHECK-DAG:  ld.param.b16    [[R4:%h[0-9]+]], [retval0+8];
423; CHECK-DAG:  st.param.v4.b16 [func_retval0+0], {[[R0]], [[R1]], [[R2]], [[R3]]};
424; CHECK-DAG:  st.param.b16    [func_retval0+8], [[R4]];
425; CHECK:      ret;
426define <5 x half> @test_v5f16(<5 x half> %a) {
427       %r = tail call <5 x half> @test_v5f16(<5 x half> %a);
428       ret <5 x half> %r;
429}
430
431; CHECK:.func  (.param .align 16 .b8 func_retval0[16])
432; CHECK-LABEL: test_v8f16(
433; CHECK:      .param .align 16 .b8 test_v8f16_param_0[16]
434; CHECK:      ld.param.v4.u32 {[[R01:%r[0-9]+]], [[R23:%r[0-9]+]], [[R45:%r[0-9]+]], [[R67:%r[0-9]+]]}, [test_v8f16_param_0];
435; CHECK-DAG:  mov.b32         [[HH01:%hh[0-9]+]], [[R01]];
436; CHECK-DAG:  mov.b32         [[HH23:%hh[0-9]+]], [[R23]];
437; CHECK-DAG:  mov.b32         [[HH45:%hh[0-9]+]], [[R45]];
438; CHECK-DAG:  mov.b32         [[HH67:%hh[0-9]+]], [[R67]];
439; CHECK:      .param .align 16 .b8 param0[16];
440; CHECK:      st.param.v4.b32 [param0+0], {[[HH01]], [[HH23]], [[HH45]], [[HH67]]};
441; CHECK:      .param .align 16 .b8 retval0[16];
442; CHECK:      call.uni (retval0),
443; CHECK:      test_v8f16,
444; CHECK:      ld.param.v4.b32 {[[RH01:%hh[0-9]+]], [[RH23:%hh[0-9]+]], [[RH45:%hh[0-9]+]], [[RH67:%hh[0-9]+]]}, [retval0+0];
445; CHECK:      st.param.v4.b32 [func_retval0+0], {[[RH01]], [[RH23]], [[RH45]], [[RH67]]};
446; CHECK:      ret;
447define <8 x half> @test_v8f16(<8 x half> %a) {
448       %r = tail call <8 x half> @test_v8f16(<8 x half> %a);
449       ret <8 x half> %r;
450}
451
452; CHECK:.func  (.param .align 32 .b8 func_retval0[32])
453; CHECK-LABEL: test_v9f16(
454; CHECK:      .param .align 32 .b8 test_v9f16_param_0[32]
455; CHECK-DAG:  ld.param.v4.b16  {[[E0:%h[0-9]+]], [[E1:%h[0-9]+]], [[E2:%h[0-9]+]], [[E3:%h[0-9]+]]}, [test_v9f16_param_0];
456; CHECK-DAG:  ld.param.v4.b16  {[[E4:%h[0-9]+]], [[E5:%h[0-9]+]], [[E6:%h[0-9]+]], [[E7:%h[0-9]+]]}, [test_v9f16_param_0+8];
457; CHECK-DAG:  ld.param.b16     [[E8:%h[0-9]+]], [test_v9f16_param_0+16];
458; CHECK:      .param .align 32 .b8 param0[32];
459; CHECK-DAG:  st.param.v4.b16 [param0+0],
460; CHECK-DAG:  st.param.v4.b16 [param0+8],
461; CHECK-DAG:  st.param.b16    [param0+16], [[E8]];
462; CHECK:      .param .align 32 .b8 retval0[32];
463; CHECK:      call.uni (retval0),
464; CHECK:      test_v9f16,
465; CHECK-DAG:  ld.param.v4.b16 {[[R0:%h[0-9]+]], [[R1:%h[0-9]+]], [[R2:%h[0-9]+]], [[R3:%h[0-9]+]]}, [retval0+0];
466; CHECK-DAG:  ld.param.v4.b16 {[[R4:%h[0-9]+]], [[R5:%h[0-9]+]], [[R6:%h[0-9]+]], [[R7:%h[0-9]+]]}, [retval0+8];
467; CHECK-DAG:  ld.param.b16    [[R8:%h[0-9]+]], [retval0+16];
468; CHECK-DAG:  st.param.v4.b16 [func_retval0+0], {[[R0]], [[R1]], [[R2]], [[R3]]};
469; CHECK-DAG:  st.param.v4.b16 [func_retval0+8], {[[R4]], [[R5]], [[R6]], [[R7]]};
470; CHECK-DAG:  st.param.b16    [func_retval0+16], [[R8]];
471; CHECK:      ret;
472define <9 x half> @test_v9f16(<9 x half> %a) {
473       %r = tail call <9 x half> @test_v9f16(<9 x half> %a);
474       ret <9 x half> %r;
475}
476
477; CHECK: .func  (.param .b32 func_retval0)
478; CHECK-LABEL: test_i32(
479; CHECK-NEXT: .param .b32 test_i32_param_0
480; CHECK:      ld.param.u32    [[E:%r[0-9]+]], [test_i32_param_0];
481; CHECK:      .param .b32 param0;
482; CHECK:      st.param.b32    [param0+0], [[E]];
483; CHECK:      .param .b32 retval0;
484; CHECK:      call.uni (retval0),
485; CHECK-NEXT: test_i32,
486; CHECK:      ld.param.b32    [[R:%r[0-9]+]], [retval0+0];
487; CHECK:      st.param.b32    [func_retval0+0], [[R]];
488; CHECK-NEXT: ret;
489define i32 @test_i32(i32 %a) {
490       %r = tail call i32 @test_i32(i32 %a);
491       ret i32 %r;
492}
493
494; CHECK: .func  (.param .align 16 .b8 func_retval0[16])
495; CHECK-LABEL: test_v3i32(
496; CHECK-NEXT: .param .align 16 .b8 test_v3i32_param_0[16]
497; CHECK-DAG:  ld.param.u32     [[E2:%r[0-9]+]], [test_v3i32_param_0+8];
498; CHECK-DAG:  ld.param.v2.u32  {[[E0:%r[0-9]+]], [[E1:%r[0-9]+]]}, [test_v3i32_param_0];
499; CHECK:      .param .align 16 .b8 param0[16];
500; CHECK:      st.param.v2.b32  [param0+0], {[[E0]], [[E1]]};
501; CHECK:      st.param.b32     [param0+8], [[E2]];
502; CHECK:      .param .align 16 .b8 retval0[16];
503; CHECK:      call.uni (retval0),
504; CHECK-NEXT: test_v3i32,
505; CHECK:      ld.param.v2.b32  {[[RE0:%r[0-9]+]], [[RE1:%r[0-9]+]]}, [retval0+0];
506; CHECK:      ld.param.b32     [[RE2:%r[0-9]+]], [retval0+8];
507; CHECK-DAG:  st.param.v2.b32  [func_retval0+0], {[[RE0]], [[RE1]]};
508; CHECK-DAG:  st.param.b32     [func_retval0+8], [[RE2]];
509; CHECK-NEXT: ret;
510define <3 x i32> @test_v3i32(<3 x i32> %a) {
511       %r = tail call <3 x i32> @test_v3i32(<3 x i32> %a);
512       ret <3 x i32> %r;
513}
514
515; CHECK: .func  (.param .align 16 .b8 func_retval0[16])
516; CHECK-LABEL: test_v4i32(
517; CHECK-NEXT: .param .align 16 .b8 test_v4i32_param_0[16]
518; CHECK:      ld.param.v4.u32  {[[E0:%r[0-9]+]], [[E1:%r[0-9]+]], [[E2:%r[0-9]+]], [[E3:%r[0-9]+]]}, [test_v4i32_param_0]
519; CHECK:      .param .align 16 .b8 param0[16];
520; CHECK:      st.param.v4.b32  [param0+0], {[[E0]], [[E1]], [[E2]], [[E3]]};
521; CHECK:      .param .align 16 .b8 retval0[16];
522; CHECK:      call.uni (retval0),
523; CHECK-NEXT: test_v4i32,
524; CHECK:      ld.param.v4.b32  {[[RE0:%r[0-9]+]], [[RE1:%r[0-9]+]], [[RE2:%r[0-9]+]], [[RE3:%r[0-9]+]]}, [retval0+0];
525; CHECK:      st.param.v4.b32  [func_retval0+0], {[[RE0]], [[RE1]], [[RE2]], [[RE3]]}
526; CHECK-NEXT: ret;
527define <4 x i32> @test_v4i32(<4 x i32> %a) {
528       %r = tail call <4 x i32> @test_v4i32(<4 x i32> %a);
529       ret <4 x i32> %r;
530}
531
532; CHECK: .func  (.param .align 32 .b8 func_retval0[32])
533; CHECK-LABEL: test_v5i32(
534; CHECK-NEXT: .param .align 32 .b8 test_v5i32_param_0[32]
535; CHECK-DAG:  ld.param.u32     [[E4:%r[0-9]+]], [test_v5i32_param_0+16];
536; CHECK-DAG:  ld.param.v4.u32  {[[E0:%r[0-9]+]], [[E1:%r[0-9]+]], [[E2:%r[0-9]+]], [[E3:%r[0-9]+]]}, [test_v5i32_param_0]
537; CHECK:      .param .align 32 .b8 param0[32];
538; CHECK-DAG:  st.param.v4.b32  [param0+0], {[[E0]], [[E1]], [[E2]], [[E3]]};
539; CHECK-DAG:  st.param.b32     [param0+16], [[E4]];
540; CHECK:      .param .align 32 .b8 retval0[32];
541; CHECK:      call.uni (retval0),
542; CHECK-NEXT: test_v5i32,
543; CHECK-DAG:  ld.param.v4.b32  {[[RE0:%r[0-9]+]], [[RE1:%r[0-9]+]], [[RE2:%r[0-9]+]], [[RE3:%r[0-9]+]]}, [retval0+0];
544; CHECK-DAG:  ld.param.b32     [[RE4:%r[0-9]+]], [retval0+16];
545; CHECK-DAG:  st.param.v4.b32  [func_retval0+0], {[[RE0]], [[RE1]], [[RE2]], [[RE3]]}
546; CHECK-DAG:  st.param.b32     [func_retval0+16], [[RE4]];
547; CHECK-NEXT: ret;
548define <5 x i32> @test_v5i32(<5 x i32> %a) {
549       %r = tail call <5 x i32> @test_v5i32(<5 x i32> %a);
550       ret <5 x i32> %r;
551}
552
553; CHECK: .func  (.param .b32 func_retval0)
554; CHECK-LABEL: test_f32(
555; CHECK-NEXT: .param .b32 test_f32_param_0
556; CHECK:      ld.param.f32    [[E:%f[0-9]+]], [test_f32_param_0];
557; CHECK:      .param .b32 param0;
558; CHECK:      st.param.f32    [param0+0], [[E]];
559; CHECK:      .param .b32 retval0;
560; CHECK:      call.uni (retval0),
561; CHECK-NEXT: test_f32,
562; CHECK:      ld.param.f32    [[R:%f[0-9]+]], [retval0+0];
563; CHECK:      st.param.f32    [func_retval0+0], [[R]];
564; CHECK-NEXT: ret;
565define float @test_f32(float %a) {
566       %r = tail call float @test_f32(float %a);
567       ret float %r;
568}
569
570; CHECK: .func  (.param .b64 func_retval0)
571; CHECK-LABEL: test_i64(
572; CHECK-NEXT: .param .b64 test_i64_param_0
573; CHECK:      ld.param.u64    [[E:%rd[0-9]+]], [test_i64_param_0];
574; CHECK:      .param .b64 param0;
575; CHECK:      st.param.b64    [param0+0], [[E]];
576; CHECK:      .param .b64 retval0;
577; CHECK:      call.uni (retval0),
578; CHECK-NEXT: test_i64,
579; CHECK:      ld.param.b64    [[R:%rd[0-9]+]], [retval0+0];
580; CHECK:      st.param.b64    [func_retval0+0], [[R]];
581; CHECK-NEXT: ret;
582define i64 @test_i64(i64 %a) {
583       %r = tail call i64 @test_i64(i64 %a);
584       ret i64 %r;
585}
586
587; CHECK: .func  (.param .align 32 .b8 func_retval0[32])
588; CHECK-LABEL: test_v3i64(
589; CHECK-NEXT: .param .align 32 .b8 test_v3i64_param_0[32]
590; CHECK-DAG:  ld.param.u64     [[E2:%rd[0-9]+]], [test_v3i64_param_0+16];
591; CHECK-DAG:  ld.param.v2.u64  {[[E0:%rd[0-9]+]], [[E1:%rd[0-9]+]]}, [test_v3i64_param_0];
592; CHECK:      .param .align 32 .b8 param0[32];
593; CHECK:      st.param.v2.b64  [param0+0], {[[E0]], [[E1]]};
594; CHECK:      st.param.b64     [param0+16], [[E2]];
595; CHECK:      .param .align 32 .b8 retval0[32];
596; CHECK:      call.uni (retval0),
597; CHECK-NEXT: test_v3i64,
598; CHECK:      ld.param.v2.b64  {[[RE0:%rd[0-9]+]], [[RE1:%rd[0-9]+]]}, [retval0+0];
599; CHECK:      ld.param.b64     [[RE2:%rd[0-9]+]], [retval0+16];
600; CHECK-DAG:  st.param.v2.b64  [func_retval0+0], {[[RE0]], [[RE1]]};
601; CHECK-DAG:  st.param.b64     [func_retval0+16], [[RE2]];
602; CHECK-DAG:  st.param.v2.b64  [func_retval0+0], {[[RE0]], [[RE1]]};
603; CHECK-DAG:  st.param.b64     [func_retval0+16], [[RE2]];
604; CHECK-NEXT: ret;
605define <3 x i64> @test_v3i64(<3 x i64> %a) {
606       %r = tail call <3 x i64> @test_v3i64(<3 x i64> %a);
607       ret <3 x i64> %r;
608}
609
610; For i64 vector loads are limited by PTX to 2 elements.
611; CHECK: .func  (.param .align 32 .b8 func_retval0[32])
612; CHECK-LABEL: test_v4i64(
613; CHECK-NEXT: .param .align 32 .b8 test_v4i64_param_0[32]
614; CHECK-DAG:  ld.param.v2.u64  {[[E2:%rd[0-9]+]], [[E3:%rd[0-9]+]]}, [test_v4i64_param_0+16];
615; CHECK-DAG:  ld.param.v2.u64  {[[E0:%rd[0-9]+]], [[E1:%rd[0-9]+]]}, [test_v4i64_param_0];
616; CHECK:      .param .align 32 .b8 param0[32];
617; CHECK:      st.param.v2.b64  [param0+0], {[[E0]], [[E1]]};
618; CHECK:      st.param.v2.b64  [param0+16], {[[E2]], [[E3]]};
619; CHECK:      .param .align 32 .b8 retval0[32];
620; CHECK:      call.uni (retval0),
621; CHECK-NEXT: test_v4i64,
622; CHECK:      ld.param.v2.b64  {[[RE0:%rd[0-9]+]], [[RE1:%rd[0-9]+]]}, [retval0+0];
623; CHECK:      ld.param.v2.b64  {[[RE2:%rd[0-9]+]], [[RE3:%rd[0-9]+]]}, [retval0+16];
624; CHECK-DAG:  st.param.v2.b64  [func_retval0+16], {[[RE2]], [[RE3]]};
625; CHECK-DAG:  st.param.v2.b64  [func_retval0+0], {[[RE0]], [[RE1]]};
626; CHECK-NEXT: ret;
627define <4 x i64> @test_v4i64(<4 x i64> %a) {
628       %r = tail call <4 x i64> @test_v4i64(<4 x i64> %a);
629       ret <4 x i64> %r;
630}
631
632; Aggregates, on the other hand, do not get extended.
633
634; CHECK: .func  (.param .align 1 .b8 func_retval0[1])
635; CHECK-LABEL: test_s_i1(
636; CHECK-NEXT: .align 1 .b8 test_s_i1_param_0[1]
637; CHECK:      ld.param.u8 [[A:%rs[0-9]+]], [test_s_i1_param_0];
638; CHECK:      .param .align 1 .b8 param0[1];
639; CHECK:      st.param.b8    [param0+0], [[A]]
640; CHECK:      .param .align 1 .b8 retval0[1];
641; CHECK:      call.uni
642; CHECK-NEXT: test_s_i1,
643; CHECK:      ld.param.b8    [[R:%rs[0-9]+]], [retval0+0];
644; CHECK:      st.param.b8    [func_retval0+0], [[R]];
645; CHECK-NEXT: ret;
646define %s_i1 @test_s_i1(%s_i1 %a) {
647       %r = tail call %s_i1 @test_s_i1(%s_i1 %a);
648       ret %s_i1 %r;
649}
650
651; CHECK: .func  (.param .align 1 .b8 func_retval0[1])
652; CHECK-LABEL: test_s_i8(
653; CHECK-NEXT: .param .align 1 .b8 test_s_i8_param_0[1]
654; CHECK:      ld.param.u8 [[A:%rs[0-9]+]], [test_s_i8_param_0];
655; CHECK:      .param .align 1 .b8 param0[1];
656; CHECK:      st.param.b8    [param0+0], [[A]]
657; CHECK:      .param .align 1 .b8 retval0[1];
658; CHECK:      call.uni
659; CHECK-NEXT: test_s_i8,
660; CHECK:      ld.param.b8    [[R:%rs[0-9]+]], [retval0+0];
661; CHECK:      st.param.b8    [func_retval0+0], [[R]];
662; CHECK-NEXT: ret;
663define %s_i8 @test_s_i8(%s_i8 %a) {
664       %r = tail call %s_i8 @test_s_i8(%s_i8 %a);
665       ret %s_i8 %r;
666}
667
668; CHECK: .func  (.param .align 2 .b8 func_retval0[2])
669; CHECK-LABEL: test_s_i16(
670; CHECK-NEXT: .param .align 2 .b8 test_s_i16_param_0[2]
671; CHECK:      ld.param.u16 [[A:%rs[0-9]+]], [test_s_i16_param_0];
672; CHECK:      .param .align 2 .b8 param0[2];
673; CHECK:      st.param.b16    [param0+0], [[A]]
674; CHECK:      .param .align 2 .b8 retval0[2];
675; CHECK:      call.uni
676; CHECK-NEXT: test_s_i16,
677; CHECK:      ld.param.b16    [[R:%rs[0-9]+]], [retval0+0];
678; CHECK:      st.param.b16    [func_retval0+0], [[R]];
679; CHECK-NEXT: ret;
680define %s_i16 @test_s_i16(%s_i16 %a) {
681       %r = tail call %s_i16 @test_s_i16(%s_i16 %a);
682       ret %s_i16 %r;
683}
684
685; CHECK: .func  (.param .align 2 .b8 func_retval0[2])
686; CHECK-LABEL: test_s_f16(
687; CHECK-NEXT: .param .align 2 .b8 test_s_f16_param_0[2]
688; CHECK:      ld.param.b16 [[A:%h[0-9]+]], [test_s_f16_param_0];
689; CHECK:      .param .align 2 .b8 param0[2];
690; CHECK:      st.param.b16    [param0+0], [[A]]
691; CHECK:      .param .align 2 .b8 retval0[2];
692; CHECK:      call.uni
693; CHECK-NEXT: test_s_f16,
694; CHECK:      ld.param.b16    [[R:%h[0-9]+]], [retval0+0];
695; CHECK:      st.param.b16    [func_retval0+0], [[R]];
696; CHECK-NEXT: ret;
697define %s_f16 @test_s_f16(%s_f16 %a) {
698       %r = tail call %s_f16 @test_s_f16(%s_f16 %a);
699       ret %s_f16 %r;
700}
701
702; CHECK: .func  (.param .align 4 .b8 func_retval0[4])
703; CHECK-LABEL: test_s_i32(
704; CHECK-NEXT: .param .align 4 .b8 test_s_i32_param_0[4]
705; CHECK:      ld.param.u32    [[E:%r[0-9]+]], [test_s_i32_param_0];
706; CHECK:      .param .align 4 .b8 param0[4]
707; CHECK:      st.param.b32    [param0+0], [[E]];
708; CHECK:      .param .align 4 .b8 retval0[4];
709; CHECK:      call.uni (retval0),
710; CHECK-NEXT: test_s_i32,
711; CHECK:      ld.param.b32    [[R:%r[0-9]+]], [retval0+0];
712; CHECK:      st.param.b32    [func_retval0+0], [[R]];
713; CHECK-NEXT: ret;
714define %s_i32 @test_s_i32(%s_i32 %a) {
715       %r = tail call %s_i32 @test_s_i32(%s_i32 %a);
716       ret %s_i32 %r;
717}
718
719; CHECK: .func  (.param .align 4 .b8 func_retval0[4])
720; CHECK-LABEL: test_s_f32(
721; CHECK-NEXT: .param .align 4 .b8 test_s_f32_param_0[4]
722; CHECK:      ld.param.f32    [[E:%f[0-9]+]], [test_s_f32_param_0];
723; CHECK:      .param .align 4 .b8 param0[4]
724; CHECK:      st.param.f32    [param0+0], [[E]];
725; CHECK:      .param .align 4 .b8 retval0[4];
726; CHECK:      call.uni (retval0),
727; CHECK-NEXT: test_s_f32,
728; CHECK:      ld.param.f32    [[R:%f[0-9]+]], [retval0+0];
729; CHECK:      st.param.f32    [func_retval0+0], [[R]];
730; CHECK-NEXT: ret;
731define %s_f32 @test_s_f32(%s_f32 %a) {
732       %r = tail call %s_f32 @test_s_f32(%s_f32 %a);
733       ret %s_f32 %r;
734}
735
736; CHECK: .func  (.param .align 8 .b8 func_retval0[8])
737; CHECK-LABEL: test_s_i64(
738; CHECK-NEXT: .param .align 8 .b8 test_s_i64_param_0[8]
739; CHECK:      ld.param.u64    [[E:%rd[0-9]+]], [test_s_i64_param_0];
740; CHECK:      .param .align 8 .b8 param0[8];
741; CHECK:      st.param.b64    [param0+0], [[E]];
742; CHECK:      .param .align 8 .b8 retval0[8];
743; CHECK:      call.uni (retval0),
744; CHECK-NEXT: test_s_i64,
745; CHECK:      ld.param.b64    [[R:%rd[0-9]+]], [retval0+0];
746; CHECK:      st.param.b64    [func_retval0+0], [[R]];
747; CHECK-NEXT: ret;
748define %s_i64 @test_s_i64(%s_i64 %a) {
749       %r = tail call %s_i64 @test_s_i64(%s_i64 %a);
750       ret %s_i64 %r;
751}
752
753; Fields that have different types, but identical sizes are not vectorized.
754; CHECK: .func  (.param .align 8 .b8 func_retval0[24])
755; CHECK-LABEL: test_s_i32f32(
756; CHECK:        .param .align 8 .b8 test_s_i32f32_param_0[24]
757; CHECK-DAG:    ld.param.u64    [[E4:%rd[0-9]+]], [test_s_i32f32_param_0+16];
758; CHECK-DAG:    ld.param.f32    [[E3:%f[0-9]+]], [test_s_i32f32_param_0+12];
759; CHECK-DAG:    ld.param.u32    [[E2:%r[0-9]+]], [test_s_i32f32_param_0+8];
760; CHECK-DAG:    ld.param.f32    [[E1:%f[0-9]+]], [test_s_i32f32_param_0+4];
761; CHECK-DAG:    ld.param.u32    [[E0:%r[0-9]+]], [test_s_i32f32_param_0];
762; CHECK:        .param .align 8 .b8 param0[24];
763; CHECK-DAG:    st.param.b32    [param0+0], [[E0]];
764; CHECK-DAG:    st.param.f32    [param0+4], [[E1]];
765; CHECK-DAG:    st.param.b32    [param0+8], [[E2]];
766; CHECK-DAG:    st.param.f32    [param0+12], [[E3]];
767; CHECK-DAG:    st.param.b64    [param0+16], [[E4]];
768; CHECK:        .param .align 8 .b8 retval0[24];
769; CHECK:        call.uni (retval0),
770; CHECK-NEXT:   test_s_i32f32,
771; CHECK-DAG:    ld.param.b32    [[RE0:%r[0-9]+]], [retval0+0];
772; CHECK-DAG:    ld.param.f32    [[RE1:%f[0-9]+]], [retval0+4];
773; CHECK-DAG:    ld.param.b32    [[RE2:%r[0-9]+]], [retval0+8];
774; CHECK-DAG:    ld.param.f32    [[RE3:%f[0-9]+]], [retval0+12];
775; CHECK-DAG:    ld.param.b64    [[RE4:%rd[0-9]+]], [retval0+16];
776; CHECK-DAG:    st.param.b32    [func_retval0+0], [[RE0]];
777; CHECK-DAG:    st.param.f32    [func_retval0+4], [[RE1]];
778; CHECK-DAG:    st.param.b32    [func_retval0+8], [[RE2]];
779; CHECK-DAG:    st.param.f32    [func_retval0+12], [[RE3]];
780; CHECK-DAG:    st.param.b64    [func_retval0+16], [[RE4]];
781; CHECK:        ret;
782define %s_i32f32 @test_s_i32f32(%s_i32f32 %a) {
783       %r = tail call %s_i32f32 @test_s_i32f32(%s_i32f32 %a);
784       ret %s_i32f32 %r;
785}
786
787; We do vectorize consecutive fields with matching types.
788; CHECK:.visible .func  (.param .align 8 .b8 func_retval0[24])
789; CHECK-LABEL: test_s_i32x4(
790; CHECK:        .param .align 8 .b8 test_s_i32x4_param_0[24]
791; CHECK-DAG:    ld.param.u64    [[RD1:%rd[0-9]+]], [test_s_i32x4_param_0+16];
792; CHECK-DAG:    ld.param.v2.u32 {[[E2:%r[0-9]+]], [[E3:%r[0-9]+]]}, [test_s_i32x4_param_0+8];
793; CHECK-DAG:    ld.param.v2.u32 {[[E0:%r[0-9]+]], [[E1:%r[0-9]+]]}, [test_s_i32x4_param_0];
794; CHECK:        .param .align 8 .b8 param0[24];
795; CHECK:        st.param.v2.b32 [param0+0], {[[E0]], [[E1]]};
796; CHECK:        st.param.v2.b32 [param0+8], {[[E2]], [[E3]]};
797; CHECK:        st.param.b64    [param0+16], [[E4]];
798; CHECK:        .param .align 8 .b8 retval0[24];
799; CHECK:        call.uni (retval0),
800; CHECK-NEXT:   test_s_i32x4,
801; CHECK:        ld.param.v2.b32 {[[RE0:%r[0-9]+]], [[RE1:%r[0-9]+]]}, [retval0+0];
802; CHECK:        ld.param.v2.b32 {[[RE2:%r[0-9]+]], [[RE3:%r[0-9]+]]}, [retval0+8];
803; CHECK:        ld.param.b64    [[RE4:%rd[0-9]+]], [retval0+16];
804; CHECK-DAG:    st.param.v2.b32 [func_retval0+0], {[[RE0]], [[RE1]]};
805; CHECK-DAG:    st.param.v2.b32 [func_retval0+8], {[[RE2]], [[RE3]]};
806; CHECK-DAG:    st.param.b64    [func_retval0+16], [[RE4]];
807; CHECK:        ret;
808
809define %s_i32x4 @test_s_i32x4(%s_i32x4 %a) {
810       %r = tail call %s_i32x4 @test_s_i32x4(%s_i32x4 %a);
811       ret %s_i32x4 %r;
812}
813
814; CHECK:.visible .func  (.param .align 8 .b8 func_retval0[32])
815; CHECK-LABEL: test_s_i1i32x4(
816; CHECK:        .param .align 8 .b8 test_s_i1i32x4_param_0[32]
817; CHECK:        ld.param.u64    [[E5:%rd[0-9]+]], [test_s_i1i32x4_param_0+24];
818; CHECK:        ld.param.u32    [[E4:%r[0-9]+]], [test_s_i1i32x4_param_0+16];
819; CHECK:        ld.param.u32    [[E3:%r[0-9]+]], [test_s_i1i32x4_param_0+12];
820; CHECK:        ld.param.u8     [[E2:%rs[0-9]+]], [test_s_i1i32x4_param_0+8];
821; CHECK:        ld.param.v2.u32         {[[E0:%r[0-9]+]], [[E1:%r[0-9]+]]}, [test_s_i1i32x4_param_0];
822; CHECK:        .param .align 8 .b8 param0[32];
823; CHECK:        st.param.v2.b32 [param0+0], {[[E0]], [[E1]]};
824; CHECK:        st.param.b8     [param0+8], [[E2]];
825; CHECK:        st.param.b32    [param0+12], [[E3]];
826; CHECK:        st.param.b32    [param0+16], [[E4]];
827; CHECK:        st.param.b64    [param0+24], [[E5]];
828; CHECK:        .param .align 8 .b8 retval0[32];
829; CHECK:        call.uni (retval0),
830; CHECK:        test_s_i1i32x4,
831; CHECK:        (
832; CHECK:        param0
833; CHECK:        );
834; CHECK:        ld.param.v2.b32 {[[RE0:%r[0-9]+]], [[RE1:%r[0-9]+]]}, [retval0+0];
835; CHECK:        ld.param.b8     [[RE2:%rs[0-9]+]], [retval0+8];
836; CHECK:        ld.param.b32    [[RE3:%r[0-9]+]], [retval0+12];
837; CHECK:        ld.param.b32    [[RE4:%r[0-9]+]], [retval0+16];
838; CHECK:        ld.param.b64    [[RE5:%rd[0-9]+]], [retval0+24];
839; CHECK:        st.param.v2.b32 [func_retval0+0], {[[RE0]], [[RE1]]};
840; CHECK:        st.param.b8     [func_retval0+8], [[RE2]];
841; CHECK:        st.param.b32    [func_retval0+12], [[RE3]];
842; CHECK:        st.param.b32    [func_retval0+16], [[RE4]];
843; CHECK:        st.param.b64    [func_retval0+24], [[RE5]];
844; CHECK:        ret;
845
846define %s_i8i32x4 @test_s_i1i32x4(%s_i8i32x4 %a) {
847       %r = tail call %s_i8i32x4 @test_s_i1i32x4(%s_i8i32x4 %a);
848       ret %s_i8i32x4 %r;
849}
850
851; -- All loads/stores from parameters aligned by one must be done one
852; -- byte at a time.
853; CHECK:.visible .func  (.param .align 1 .b8 func_retval0[25])
854; CHECK-LABEL: test_s_i1i32x4p(
855; CHECK-DAG:        .param .align 1 .b8 test_s_i1i32x4p_param_0[25]
856; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+24];
857; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+23];
858; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+22];
859; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+21];
860; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+20];
861; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+19];
862; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+18];
863; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+17];
864; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+16];
865; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+15];
866; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+14];
867; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+13];
868; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+12];
869; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+11];
870; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+10];
871; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+9];
872; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+8];
873; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+7];
874; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+6];
875; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+5];
876; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+4];
877; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+3];
878; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+2];
879; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0+1];
880; CHECK-DAG:        ld.param.u8     %r{{.*}}, [test_s_i1i32x4p_param_0];
881; --- TODO
882; --- Unaligned parameter store/ return value load is broken in both nvcc
883; --- and llvm and needs to be fixed.
884; CHECK:        .param .align 1 .b8 param0[25];
885; CHECK-DAG:        st.param.b32    [param0+0],
886; CHECK-DAG:        st.param.b32    [param0+4],
887; CHECK-DAG:        st.param.b8     [param0+8],
888; CHECK-DAG:        st.param.b32    [param0+9],
889; CHECK-DAG:        st.param.b32    [param0+13],
890; CHECK-DAG:        st.param.b64    [param0+17],
891; CHECK:            .param .align 1 .b8 retval0[25];
892; CHECK:            call.uni (retval0),
893; CHECK-NEXT:       test_s_i1i32x4p,
894; CHECK-DAG:        ld.param.b32    %r41, [retval0+0];
895; CHECK-DAG:        ld.param.b32    %r42, [retval0+4];
896; CHECK-DAG:        ld.param.b8     %rs2, [retval0+8];
897; CHECK-DAG:        ld.param.b32    %r43, [retval0+9];
898; CHECK-DAG:        ld.param.b32    %r44, [retval0+13];
899; CHECK-DAG:        ld.param.b64    %rd23, [retval0+17];
900; CHECK-DAG:        st.param.b32    [func_retval0+0],
901; CHECK-DAG:        st.param.b32    [func_retval0+4],
902; CHECK-DAG:        st.param.b8     [func_retval0+8],
903; CHECK-DAG:        st.param.b32    [func_retval0+9],
904; CHECK-DAG:        st.param.b32    [func_retval0+13],
905; CHECK-DAG:        st.param.b64    [func_retval0+17],
906
907define %s_i8i32x4p @test_s_i1i32x4p(%s_i8i32x4p %a) {
908       %r = tail call %s_i8i32x4p @test_s_i1i32x4p(%s_i8i32x4p %a);
909       ret %s_i8i32x4p %r;
910}
911
912; Check that we can vectorize loads that span multiple aggregate fields.
913; CHECK:.visible .func  (.param .align 16 .b8 func_retval0[80])
914; CHECK-LABEL: test_s_crossfield(
915; CHECK:        .param .align 16 .b8 test_s_crossfield_param_0[80]
916; CHECK:        ld.param.u32    [[E15:%r[0-9]+]], [test_s_crossfield_param_0+64];
917; CHECK:        ld.param.v4.u32 {[[E11:%r[0-9]+]], [[E12:%r[0-9]+]], [[E13:%r[0-9]+]], [[E14:%r[0-9]+]]}, [test_s_crossfield_param_0+48];
918; CHECK:        ld.param.v4.u32 {[[E7:%r[0-9]+]], [[E8:%r[0-9]+]], [[E9:%r[0-9]+]], [[E10:%r[0-9]+]]}, [test_s_crossfield_param_0+32];
919; CHECK:        ld.param.v4.u32 {[[E3:%r[0-9]+]], [[E4:%r[0-9]+]], [[E5:%r[0-9]+]], [[E6:%r[0-9]+]]}, [test_s_crossfield_param_0+16];
920; CHECK:        ld.param.u32    [[E2:%r[0-9]+]], [test_s_crossfield_param_0+8];
921; CHECK:        ld.param.v2.u32 {[[E0:%r[0-9]+]], [[E1:%r[0-9]+]]}, [test_s_crossfield_param_0];
922; CHECK:        .param .align 16 .b8 param0[80];
923; CHECK:        st.param.v2.b32 [param0+0], {[[E0]], [[E1]]};
924; CHECK:        st.param.b32    [param0+8], [[E2]];
925; CHECK:        st.param.v4.b32 [param0+16], {[[E3]], [[E4]], [[E5]], [[E6]]};
926; CHECK:        st.param.v4.b32 [param0+32], {[[E7]], [[E8]], [[E9]], [[E10]]};
927; CHECK:        st.param.v4.b32 [param0+48], {[[E11]], [[E12]], [[E13]], [[E14]]};
928; CHECK:        st.param.b32    [param0+64], [[E15]];
929; CHECK:        .param .align 16 .b8 retval0[80];
930; CHECK:        call.uni (retval0),
931; CHECK:        test_s_crossfield,
932; CHECK:        ld.param.v2.b32 {[[RE0:%r[0-9]+]], [[RE1:%r[0-9]+]]}, [retval0+0];
933; CHECK:        ld.param.b32    [[RE2:%r[0-9]+]], [retval0+8];
934; CHECK:        ld.param.v4.b32 {[[RE3:%r[0-9]+]], [[RE4:%r[0-9]+]], [[RE5:%r[0-9]+]], [[RE6:%r[0-9]+]]}, [retval0+16];
935; CHECK:        ld.param.v4.b32 {[[RE7:%r[0-9]+]], [[RE8:%r[0-9]+]], [[RE9:%r[0-9]+]], [[RE10:%r[0-9]+]]}, [retval0+32];
936; CHECK:        ld.param.v4.b32 {[[RE11:%r[0-9]+]], [[RE12:%r[0-9]+]], [[RE13:%r[0-9]+]], [[RE14:%r[0-9]+]]}, [retval0+48];
937; CHECK:        ld.param.b32    [[RE15:%r[0-9]+]], [retval0+64];
938; CHECK:        st.param.v2.b32 [func_retval0+0], {[[RE0]], [[RE1]]};
939; CHECK:        st.param.b32    [func_retval0+8], [[RE2]];
940; CHECK:        st.param.v4.b32 [func_retval0+16], {[[RE3]], [[RE4]], [[RE5]], [[RE6]]};
941; CHECK:        st.param.v4.b32 [func_retval0+32], {[[RE7]], [[RE8]], [[RE9]], [[RE10]]};
942; CHECK:        st.param.v4.b32 [func_retval0+48], {[[RE11]], [[RE12]], [[RE13]], [[RE14]]};
943; CHECK:        st.param.b32    [func_retval0+64], [[RE15]];
944; CHECK:        ret;
945
946define %s_crossfield @test_s_crossfield(%s_crossfield %a) {
947       %r = tail call %s_crossfield @test_s_crossfield(%s_crossfield %a);
948       ret %s_crossfield %r;
949}
950