1; RUN: llc -mtriple=amdgcn--amdhsa -mcpu=gfx901 -mattr=-flat-for-global,+fp64-fp16-denormals -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=GFX9 -check-prefix=GFX9-DENORM %s
2; RUN: llc -mtriple=amdgcn--amdhsa -mcpu=gfx901 -mattr=-flat-for-global,-fp64-fp16-denormals -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=GFX9 -check-prefix=GFX9-FLUSH %s
3; RUN: llc -mtriple=amdgcn--amdhsa -mcpu=fiji -mattr=-flat-for-global -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=VI %s
4; RUN: llc -mtriple=amdgcn--amdhsa -mcpu=kaveri -mattr=-flat-for-global -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=CI %s
5
6
7; GCN-LABEL: {{^}}s_pack_v2i16:
8; GFX9: s_load_dword [[VAL0:s[0-9]+]]
9; GFX9: s_load_dword [[VAL1:s[0-9]+]]
10; GFX9: s_pack_ll_b32_b16 [[PACKED:s[0-9]+]], [[VAL0]], [[VAL1]]
11; GFX9: ; use [[PACKED]]
12define void @s_pack_v2i16(i32 addrspace(2)* %in0, i32 addrspace(2)* %in1) #0 {
13  %val0 = load volatile i32, i32 addrspace(2)* %in0
14  %val1 = load volatile i32, i32 addrspace(2)* %in1
15  %lo = trunc i32 %val0 to i16
16  %hi = trunc i32 %val1 to i16
17  %vec.0 = insertelement <2 x i16> undef, i16 %lo, i32 0
18  %vec.1 = insertelement <2 x i16> %vec.0, i16 %hi, i32 1
19  %vec.i32 = bitcast <2 x i16> %vec.1 to i32
20
21  call void asm sideeffect "; use $0", "s"(i32 %vec.i32) #0
22  ret void
23}
24
25; GCN-LABEL: {{^}}s_pack_v2i16_imm_lo:
26; GFX9: s_load_dword [[VAL1:s[0-9]+]]
27; GFX9: s_pack_ll_b32_b16 [[PACKED:s[0-9]+]], 0x1c8, [[VAL1]]
28; GFX9: ; use [[PACKED]]
29define void @s_pack_v2i16_imm_lo(i32 addrspace(2)* %in1) #0 {
30  %val1 = load i32, i32 addrspace(2)* %in1
31  %hi = trunc i32 %val1 to i16
32  %vec.0 = insertelement <2 x i16> undef, i16 456, i32 0
33  %vec.1 = insertelement <2 x i16> %vec.0, i16 %hi, i32 1
34  %vec.i32 = bitcast <2 x i16> %vec.1 to i32
35
36  call void asm sideeffect "; use $0", "s"(i32 %vec.i32) #0
37  ret void
38}
39
40; GCN-LABEL: {{^}}s_pack_v2i16_imm_hi:
41; GFX9: s_load_dword [[VAL0:s[0-9]+]]
42; GFX9: s_pack_ll_b32_b16 [[PACKED:s[0-9]+]], [[VAL0]], 0x1c8
43; GFX9: ; use [[PACKED]]
44define void @s_pack_v2i16_imm_hi(i32 addrspace(2)* %in0) #0 {
45  %val0 = load i32, i32 addrspace(2)* %in0
46  %lo = trunc i32 %val0 to i16
47  %vec.0 = insertelement <2 x i16> undef, i16 %lo, i32 0
48  %vec.1 = insertelement <2 x i16> %vec.0, i16 456, i32 1
49  %vec.i32 = bitcast <2 x i16> %vec.1 to i32
50
51  call void asm sideeffect "; use $0", "s"(i32 %vec.i32) #0
52  ret void
53}
54
55; GCN-LABEL: {{^}}v_pack_v2i16:
56; GFX9: flat_load_dword [[VAL0:v[0-9]+]]
57; GFX9: flat_load_dword [[VAL1:v[0-9]+]]
58; GFX9-DENORM: v_pack_b32_f16 [[PACKED:v[0-9]+]], [[VAL0]], [[VAL1]]
59
60; GFX9-FLUSH: v_and_b32_e32 [[MASKED:v[0-9]+]], 0xffff, [[VAL0]]
61; GFX9-FLUSH: v_lshl_or_b32 [[PACKED:v[0-9]+]], [[VAL1]], 16, [[MASKED]]
62; GFX9: ; use [[PACKED]]
63define void @v_pack_v2i16(i32 addrspace(1)* %in0, i32 addrspace(1)* %in1) #0 {
64  %tid = call i32 @llvm.amdgcn.workitem.id.x()
65  %tid.ext = sext i32 %tid to i64
66  %in0.gep = getelementptr inbounds i32, i32 addrspace(1)* %in0, i64 %tid.ext
67  %in1.gep = getelementptr inbounds i32, i32 addrspace(1)* %in1, i64 %tid.ext
68  %val0 = load volatile i32, i32 addrspace(1)* %in0.gep
69  %val1 = load volatile i32, i32 addrspace(1)* %in1.gep
70  %lo = trunc i32 %val0 to i16
71  %hi = trunc i32 %val1 to i16
72  %vec.0 = insertelement <2 x i16> undef, i16 %lo, i32 0
73  %vec.1 = insertelement <2 x i16> %vec.0, i16 %hi, i32 1
74  %vec.i32 = bitcast <2 x i16> %vec.1 to i32
75  call void asm sideeffect "; use $0", "v"(i32 %vec.i32) #0
76  ret void
77}
78
79; GCN-LABEL: {{^}}v_pack_v2i16_user:
80; GFX9: flat_load_dword [[VAL0:v[0-9]+]]
81; GFX9: flat_load_dword [[VAL1:v[0-9]+]]
82; GFX9-DENORM: v_pack_b32_f16 [[PACKED:v[0-9]+]], [[VAL0]], [[VAL1]]
83
84; GFX9-FLUSH: v_and_b32_e32 [[MASKED:v[0-9]+]], 0xffff, [[VAL0]]
85; GFX9-FLUSH: v_lshl_or_b32 [[PACKED:v[0-9]+]], [[VAL1]], 16, [[MASKED]]
86
87; GFX9: v_add_i32_e32 v{{[0-9]+}}, vcc, 9, [[PACKED]]
88define void @v_pack_v2i16_user(i32 addrspace(1)* %in0, i32 addrspace(1)* %in1) #0 {
89  %tid = call i32 @llvm.amdgcn.workitem.id.x()
90  %tid.ext = sext i32 %tid to i64
91  %in0.gep = getelementptr inbounds i32, i32 addrspace(1)* %in0, i64 %tid.ext
92  %in1.gep = getelementptr inbounds i32, i32 addrspace(1)* %in1, i64 %tid.ext
93  %val0 = load volatile i32, i32 addrspace(1)* %in0.gep
94  %val1 = load volatile i32, i32 addrspace(1)* %in1.gep
95  %lo = trunc i32 %val0 to i16
96  %hi = trunc i32 %val1 to i16
97  %vec.0 = insertelement <2 x i16> undef, i16 %lo, i32 0
98  %vec.1 = insertelement <2 x i16> %vec.0, i16 %hi, i32 1
99  %vec.i32 = bitcast <2 x i16> %vec.1 to i32
100  %foo = add i32 %vec.i32, 9
101  store volatile i32 %foo, i32 addrspace(1)* undef
102  ret void
103}
104
105; GCN-LABEL: {{^}}v_pack_v2i16_imm_lo:
106; GFX9: flat_load_dword [[VAL1:v[0-9]+]]
107; GFX9-DENORM: s_movk_i32 [[K:s[0-9]+]], 0x7b{{$}}
108; GFX9-DENORM: v_pack_b32_f16 [[PACKED:v[0-9]+]], [[K]], [[VAL1]]
109
110; GFX9-FLUSH: v_mov_b32_e32 [[K:v[0-9]+]], 0x7b{{$}}
111; GFX9-FLUSH: v_lshl_or_b32 [[PACKED:v[0-9]+]], [[VAL1]], 16, [[K]]
112
113; GFX9: ; use [[PACKED]]
114define void @v_pack_v2i16_imm_lo(i32 addrspace(1)* %in1) #0 {
115  %tid = call i32 @llvm.amdgcn.workitem.id.x()
116  %tid.ext = sext i32 %tid to i64
117  %in1.gep = getelementptr inbounds i32, i32 addrspace(1)* %in1, i64 %tid.ext
118  %val1 = load volatile i32, i32 addrspace(1)* %in1.gep
119  %hi = trunc i32 %val1 to i16
120  %vec.0 = insertelement <2 x i16> undef, i16 123, i32 0
121  %vec.1 = insertelement <2 x i16> %vec.0, i16 %hi, i32 1
122  %vec.i32 = bitcast <2 x i16> %vec.1 to i32
123  call void asm sideeffect "; use $0", "v"(i32 %vec.i32) #0
124  ret void
125}
126
127; GCN-LABEL: {{^}}v_pack_v2i16_inline_imm_lo:
128; GFX9: flat_load_dword [[VAL1:v[0-9]+]]
129; GFX9-DENORM: v_pack_b32_f16 [[PACKED:v[0-9]+]], 64, [[VAL1]]
130
131; GFX9-FLUSH: v_lshl_or_b32 [[PACKED:v[0-9]+]], [[VAL1]], 16, 64
132; GFX9: ; use [[PACKED]]
133define void @v_pack_v2i16_inline_imm_lo(i32 addrspace(1)* %in1) #0 {
134  %tid = call i32 @llvm.amdgcn.workitem.id.x()
135  %tid.ext = sext i32 %tid to i64
136  %in1.gep = getelementptr inbounds i32, i32 addrspace(1)* %in1, i64 %tid.ext
137  %val1 = load volatile i32, i32 addrspace(1)* %in1.gep
138  %hi = trunc i32 %val1 to i16
139  %vec.0 = insertelement <2 x i16> undef, i16 64, i32 0
140  %vec.1 = insertelement <2 x i16> %vec.0, i16 %hi, i32 1
141  %vec.i32 = bitcast <2 x i16> %vec.1 to i32
142  call void asm sideeffect "; use $0", "v"(i32 %vec.i32) #0
143  ret void
144}
145
146; GCN-LABEL: {{^}}v_pack_v2i16_imm_hi:
147; GFX9: flat_load_dword [[VAL0:v[0-9]+]]
148; GFX9-DENORM: v_pack_b32_f16 [[PACKED:v[0-9]+]], [[VAL0]], [[K]]
149
150; GFX9-FLUSH: s_movk_i32 [[K:s[0-9]+]], 0x7b{{$}}
151; GFX9-FLUSH: v_lshl_or_b32 [[PACKED:v[0-9]+]], [[K]], 16, [[VAL0]]
152
153; GFX9: ; use [[PACKED]]
154define void @v_pack_v2i16_imm_hi(i32 addrspace(1)* %in0) #0 {
155  %tid = call i32 @llvm.amdgcn.workitem.id.x()
156  %tid.ext = sext i32 %tid to i64
157  %in0.gep = getelementptr inbounds i32, i32 addrspace(1)* %in0, i64 %tid.ext
158  %val0 = load volatile i32, i32 addrspace(1)* %in0.gep
159  %lo = trunc i32 %val0 to i16
160  %vec.0 = insertelement <2 x i16> undef, i16 %lo, i32 0
161  %vec.1 = insertelement <2 x i16> %vec.0, i16 123, i32 1
162  %vec.i32 = bitcast <2 x i16> %vec.1 to i32
163  call void asm sideeffect "; use $0", "v"(i32 %vec.i32) #0
164  ret void
165}
166
167; GCN-LABEL: {{^}}v_pack_v2i16_inline_imm_hi:
168; GFX9: flat_load_dword [[VAL:v[0-9]+]]
169; GFX9-DENORM: v_pack_b32_f16 [[PACKED:v[0-9]+]], [[VAL]], 7
170; GFX9-FLUSH: v_lshl_or_b32 [[PACKED:v[0-9]+]], 7, 16, [[VAL0]]
171; GFX9: ; use [[PACKED]]
172define void @v_pack_v2i16_inline_imm_hi(i32 addrspace(1)* %in0) #0 {
173  %tid = call i32 @llvm.amdgcn.workitem.id.x()
174  %tid.ext = sext i32 %tid to i64
175  %in0.gep = getelementptr inbounds i32, i32 addrspace(1)* %in0, i64 %tid.ext
176  %val0 = load volatile i32, i32 addrspace(1)* %in0.gep
177  %lo = trunc i32 %val0 to i16
178  %vec.0 = insertelement <2 x i16> undef, i16 %lo, i32 0
179  %vec.1 = insertelement <2 x i16> %vec.0, i16 7, i32 1
180  %vec.i32 = bitcast <2 x i16> %vec.1 to i32
181  call void asm sideeffect "; use $0", "v"(i32 %vec.i32) #0
182  ret void
183}
184
185declare i32 @llvm.amdgcn.workitem.id.x() #1
186
187attributes #0 = { nounwind }
188attributes #1 = { nounwind readnone }
189