Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / test / CodeGen / AMDGPU / GlobalISel / mul-known-bits.i64.ll
blobb1f617cfb52a93cd9502550daa8c11c944802cc9
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN:  llc -march=amdgcn -mcpu=gfx1010 -global-isel=1 -verify-machineinstrs < %s | FileCheck -allow-deprecated-dag-overlap -check-prefixes=GFX10 %s
3 ; RUN:  llc -march=amdgcn -mcpu=gfx1100 -global-isel=1 -verify-machineinstrs < %s | FileCheck -allow-deprecated-dag-overlap -check-prefixes=GFX11 %s
4 declare i32 @llvm.amdgcn.workitem.id.x()
6 ; A 64-bit multiplication where no arguments were zero extended.
7 define amdgpu_kernel void @v_mul_i64_no_zext(ptr addrspace(1) %out, ptr addrspace(1) %aptr, ptr addrspace(1) %bptr) nounwind {
8 ; GFX10-LABEL: v_mul_i64_no_zext:
9 ; GFX10:       ; %bb.0:
10 ; GFX10-NEXT:    s_load_dwordx4 s[0:3], s[0:1], 0x2c
11 ; GFX10-NEXT:    v_lshlrev_b32_e32 v6, 3, v0
12 ; GFX10-NEXT:    s_waitcnt lgkmcnt(0)
13 ; GFX10-NEXT:    s_clause 0x1
14 ; GFX10-NEXT:    global_load_dwordx2 v[0:1], v6, s[0:1]
15 ; GFX10-NEXT:    global_load_dwordx2 v[2:3], v6, s[2:3]
16 ; GFX10-NEXT:    s_waitcnt vmcnt(0)
17 ; GFX10-NEXT:    v_mad_u64_u32 v[4:5], s0, v0, v2, 0
18 ; GFX10-NEXT:    v_mul_lo_u32 v0, v0, v3
19 ; GFX10-NEXT:    v_mul_lo_u32 v1, v1, v2
20 ; GFX10-NEXT:    v_add3_u32 v5, v5, v0, v1
21 ; GFX10-NEXT:    global_store_dwordx2 v6, v[4:5], s[2:3]
22 ; GFX10-NEXT:    s_endpgm
24 ; GFX11-LABEL: v_mul_i64_no_zext:
25 ; GFX11:       ; %bb.0:
26 ; GFX11-NEXT:    s_load_b128 s[0:3], s[0:1], 0x2c
27 ; GFX11-NEXT:    v_lshlrev_b32_e32 v6, 3, v0
28 ; GFX11-NEXT:    s_waitcnt lgkmcnt(0)
29 ; GFX11-NEXT:    s_clause 0x1
30 ; GFX11-NEXT:    global_load_b64 v[0:1], v6, s[0:1]
31 ; GFX11-NEXT:    global_load_b64 v[2:3], v6, s[2:3]
32 ; GFX11-NEXT:    s_waitcnt vmcnt(0)
33 ; GFX11-NEXT:    v_mad_u64_u32 v[4:5], null, v0, v2, 0
34 ; GFX11-NEXT:    v_mul_lo_u32 v0, v0, v3
35 ; GFX11-NEXT:    v_mul_lo_u32 v1, v1, v2
36 ; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1)
37 ; GFX11-NEXT:    v_add3_u32 v5, v5, v0, v1
38 ; GFX11-NEXT:    global_store_b64 v6, v[4:5], s[2:3]
39 ; GFX11-NEXT:    s_nop 0
40 ; GFX11-NEXT:    s_sendmsg sendmsg(MSG_DEALLOC_VGPRS)
41 ; GFX11-NEXT:    s_endpgm
42   %tid = call i32 @llvm.amdgcn.workitem.id.x()
43   %gep.a = getelementptr inbounds i64, ptr addrspace(1) %aptr, i32 %tid
44   %gep.b = getelementptr inbounds i64, ptr addrspace(1) %bptr, i32 %tid
45   %gep.out = getelementptr inbounds i64, ptr addrspace(1) %bptr, i32 %tid
46   %a = load i64, ptr addrspace(1) %gep.a
47   %b = load i64, ptr addrspace(1) %gep.b
48   %mul = mul i64 %a, %b
49   store i64 %mul, ptr addrspace(1) %gep.out
50   ret void
53 ; a 64 bit multiplication where the second argument was zero extended.
54 define amdgpu_kernel void @v_mul_i64_zext_src1(ptr addrspace(1) %out, ptr addrspace(1) %aptr, ptr addrspace(1) %bptr) {
55 ; GFX10-LABEL: v_mul_i64_zext_src1:
56 ; GFX10:       ; %bb.0:
57 ; GFX10-NEXT:    s_clause 0x1
58 ; GFX10-NEXT:    s_load_dwordx4 s[4:7], s[0:1], 0x24
59 ; GFX10-NEXT:    s_load_dwordx2 s[2:3], s[0:1], 0x34
60 ; GFX10-NEXT:    v_lshlrev_b32_e32 v2, 3, v0
61 ; GFX10-NEXT:    v_lshlrev_b32_e32 v3, 2, v0
62 ; GFX10-NEXT:    s_waitcnt lgkmcnt(0)
63 ; GFX10-NEXT:    global_load_dwordx2 v[0:1], v2, s[6:7]
64 ; GFX10-NEXT:    global_load_dword v4, v3, s[2:3]
65 ; GFX10-NEXT:    s_waitcnt vmcnt(0)
66 ; GFX10-NEXT:    v_mad_u64_u32 v[2:3], s0, v0, v4, 0
67 ; GFX10-NEXT:    v_mul_lo_u32 v0, v1, v4
68 ; GFX10-NEXT:    v_add_nc_u32_e32 v3, v3, v0
69 ; GFX10-NEXT:    v_mov_b32_e32 v0, 0
70 ; GFX10-NEXT:    global_store_dwordx2 v0, v[2:3], s[4:5]
71 ; GFX10-NEXT:    s_endpgm
73 ; GFX11-LABEL: v_mul_i64_zext_src1:
74 ; GFX11:       ; %bb.0:
75 ; GFX11-NEXT:    s_clause 0x1
76 ; GFX11-NEXT:    s_load_b128 s[4:7], s[0:1], 0x24
77 ; GFX11-NEXT:    s_load_b64 s[0:1], s[0:1], 0x34
78 ; GFX11-NEXT:    v_lshlrev_b32_e32 v1, 3, v0
79 ; GFX11-NEXT:    v_lshlrev_b32_e32 v2, 2, v0
80 ; GFX11-NEXT:    s_waitcnt lgkmcnt(0)
81 ; GFX11-NEXT:    global_load_b64 v[0:1], v1, s[6:7]
82 ; GFX11-NEXT:    global_load_b32 v4, v2, s[0:1]
83 ; GFX11-NEXT:    s_waitcnt vmcnt(0)
84 ; GFX11-NEXT:    v_mad_u64_u32 v[2:3], null, v0, v4, 0
85 ; GFX11-NEXT:    v_mul_lo_u32 v0, v1, v4
86 ; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1)
87 ; GFX11-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_add_nc_u32 v3, v3, v0
88 ; GFX11-NEXT:    global_store_b64 v0, v[2:3], s[4:5]
89 ; GFX11-NEXT:    s_nop 0
90 ; GFX11-NEXT:    s_sendmsg sendmsg(MSG_DEALLOC_VGPRS)
91 ; GFX11-NEXT:    s_endpgm
92   %tid = call i32 @llvm.amdgcn.workitem.id.x()
93   %gep.a = getelementptr inbounds i64, ptr addrspace(1) %aptr, i32 %tid
94   %gep.b = getelementptr inbounds i32, ptr addrspace(1) %bptr, i32 %tid
95   %a = load i64, ptr addrspace(1) %gep.a
96   %b = load i32, ptr addrspace(1) %gep.b
97   %b_ext = zext i32 %b to i64
98   %mul = mul i64 %a, %b_ext
99   store i64 %mul, ptr addrspace(1) %out
100   ret void
103 ; 64 bit multiplication where the first argument was zero extended.
104 define amdgpu_kernel void @v_mul_i64_zext_src0(ptr addrspace(1) %out, ptr addrspace(1) %aptr, ptr addrspace(1) %bptr) {
105 ; GFX10-LABEL: v_mul_i64_zext_src0:
106 ; GFX10:       ; %bb.0:
107 ; GFX10-NEXT:    s_clause 0x1
108 ; GFX10-NEXT:    s_load_dwordx4 s[4:7], s[0:1], 0x24
109 ; GFX10-NEXT:    s_load_dwordx2 s[2:3], s[0:1], 0x34
110 ; GFX10-NEXT:    v_lshlrev_b32_e32 v2, 2, v0
111 ; GFX10-NEXT:    v_lshlrev_b32_e32 v3, 3, v0
112 ; GFX10-NEXT:    s_waitcnt lgkmcnt(0)
113 ; GFX10-NEXT:    global_load_dword v4, v2, s[6:7]
114 ; GFX10-NEXT:    global_load_dwordx2 v[0:1], v3, s[2:3]
115 ; GFX10-NEXT:    s_waitcnt vmcnt(0)
116 ; GFX10-NEXT:    v_mad_u64_u32 v[2:3], s0, v4, v0, 0
117 ; GFX10-NEXT:    v_mul_lo_u32 v0, v4, v1
118 ; GFX10-NEXT:    v_add_nc_u32_e32 v3, v3, v0
119 ; GFX10-NEXT:    v_mov_b32_e32 v0, 0
120 ; GFX10-NEXT:    global_store_dwordx2 v0, v[2:3], s[4:5]
121 ; GFX10-NEXT:    s_endpgm
123 ; GFX11-LABEL: v_mul_i64_zext_src0:
124 ; GFX11:       ; %bb.0:
125 ; GFX11-NEXT:    s_clause 0x1
126 ; GFX11-NEXT:    s_load_b128 s[4:7], s[0:1], 0x24
127 ; GFX11-NEXT:    s_load_b64 s[0:1], s[0:1], 0x34
128 ; GFX11-NEXT:    v_lshlrev_b32_e32 v1, 2, v0
129 ; GFX11-NEXT:    v_lshlrev_b32_e32 v0, 3, v0
130 ; GFX11-NEXT:    s_waitcnt lgkmcnt(0)
131 ; GFX11-NEXT:    global_load_b32 v4, v1, s[6:7]
132 ; GFX11-NEXT:    global_load_b64 v[0:1], v0, s[0:1]
133 ; GFX11-NEXT:    s_waitcnt vmcnt(0)
134 ; GFX11-NEXT:    v_mad_u64_u32 v[2:3], null, v4, v0, 0
135 ; GFX11-NEXT:    v_mul_lo_u32 v0, v4, v1
136 ; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1)
137 ; GFX11-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_add_nc_u32 v3, v3, v0
138 ; GFX11-NEXT:    global_store_b64 v0, v[2:3], s[4:5]
139 ; GFX11-NEXT:    s_nop 0
140 ; GFX11-NEXT:    s_sendmsg sendmsg(MSG_DEALLOC_VGPRS)
141 ; GFX11-NEXT:    s_endpgm
142   %tid = call i32 @llvm.amdgcn.workitem.id.x()
143   %gep.a = getelementptr inbounds i32, ptr addrspace(1) %aptr, i32 %tid
144   %gep.b = getelementptr inbounds i64, ptr addrspace(1) %bptr, i32 %tid
145   %a = load i32, ptr addrspace(1) %gep.a
146   %b = load i64, ptr addrspace(1) %gep.b
147   %a_ext = zext i32 %a to i64
148   %mul = mul i64 %a_ext, %b
149   store i64 %mul, ptr addrspace(1) %out
150   ret void
153 ; 64-bit multiplication where both arguments were zero extended.
154 define amdgpu_kernel void @v_mul_i64_zext_src0_src1(ptr addrspace(1) %out, ptr addrspace(1) %aptr, ptr addrspace(1) %bptr) {
155 ; GFX10-LABEL: v_mul_i64_zext_src0_src1:
156 ; GFX10:       ; %bb.0:
157 ; GFX10-NEXT:    s_clause 0x1
158 ; GFX10-NEXT:    s_load_dwordx4 s[4:7], s[0:1], 0x24
159 ; GFX10-NEXT:    s_load_dwordx2 s[2:3], s[0:1], 0x34
160 ; GFX10-NEXT:    v_lshlrev_b32_e32 v0, 2, v0
161 ; GFX10-NEXT:    s_waitcnt lgkmcnt(0)
162 ; GFX10-NEXT:    s_clause 0x1
163 ; GFX10-NEXT:    global_load_dword v1, v0, s[6:7]
164 ; GFX10-NEXT:    global_load_dword v2, v0, s[2:3]
165 ; GFX10-NEXT:    s_waitcnt vmcnt(0)
166 ; GFX10-NEXT:    v_mad_u64_u32 v[0:1], s0, v1, v2, 0
167 ; GFX10-NEXT:    v_mov_b32_e32 v2, 0
168 ; GFX10-NEXT:    global_store_dwordx2 v2, v[0:1], s[4:5]
169 ; GFX10-NEXT:    s_endpgm
171 ; GFX11-LABEL: v_mul_i64_zext_src0_src1:
172 ; GFX11:       ; %bb.0:
173 ; GFX11-NEXT:    s_clause 0x1
174 ; GFX11-NEXT:    s_load_b128 s[4:7], s[0:1], 0x24
175 ; GFX11-NEXT:    s_load_b64 s[0:1], s[0:1], 0x34
176 ; GFX11-NEXT:    v_lshlrev_b32_e32 v0, 2, v0
177 ; GFX11-NEXT:    v_mov_b32_e32 v2, 0
178 ; GFX11-NEXT:    s_waitcnt lgkmcnt(0)
179 ; GFX11-NEXT:    s_clause 0x1
180 ; GFX11-NEXT:    global_load_b32 v1, v0, s[6:7]
181 ; GFX11-NEXT:    global_load_b32 v0, v0, s[0:1]
182 ; GFX11-NEXT:    s_waitcnt vmcnt(0)
183 ; GFX11-NEXT:    v_mad_u64_u32 v[0:1], null, v1, v0, 0
184 ; GFX11-NEXT:    global_store_b64 v2, v[0:1], s[4:5]
185 ; GFX11-NEXT:    s_nop 0
186 ; GFX11-NEXT:    s_sendmsg sendmsg(MSG_DEALLOC_VGPRS)
187 ; GFX11-NEXT:    s_endpgm
188   %tid = call i32 @llvm.amdgcn.workitem.id.x()
189   %gep.a = getelementptr inbounds i32, ptr addrspace(1) %aptr, i32 %tid
190   %gep.b = getelementptr inbounds i32, ptr addrspace(1) %bptr, i32 %tid
191   %a = load i32, ptr addrspace(1) %gep.a
192   %b = load i32, ptr addrspace(1) %gep.b
193   %a_ext = zext i32 %a to i64
194   %b_ext = zext i32 %b to i64
195   %mul = mul i64 %a_ext, %b_ext
196   store i64 %mul, ptr addrspace(1) %out
197   ret void
200 ; 64-bit multiplication where the upper bytes of the first argument were masked.
201 define amdgpu_kernel void @v_mul_i64_masked_src0_hi(ptr addrspace(1) %out, ptr addrspace(1) %aptr, ptr addrspace(1) %bptr) {
202 ; GFX10-LABEL: v_mul_i64_masked_src0_hi:
203 ; GFX10:       ; %bb.0:
204 ; GFX10-NEXT:    s_clause 0x1
205 ; GFX10-NEXT:    s_load_dwordx4 s[4:7], s[0:1], 0x24
206 ; GFX10-NEXT:    s_load_dwordx2 s[2:3], s[0:1], 0x34
207 ; GFX10-NEXT:    v_lshlrev_b32_e32 v2, 3, v0
208 ; GFX10-NEXT:    s_waitcnt lgkmcnt(0)
209 ; GFX10-NEXT:    s_clause 0x1
210 ; GFX10-NEXT:    global_load_dword v4, v2, s[6:7]
211 ; GFX10-NEXT:    global_load_dwordx2 v[0:1], v2, s[2:3]
212 ; GFX10-NEXT:    s_waitcnt vmcnt(0)
213 ; GFX10-NEXT:    v_mad_u64_u32 v[2:3], s0, v4, v0, 0
214 ; GFX10-NEXT:    v_mul_lo_u32 v0, v4, v1
215 ; GFX10-NEXT:    v_add_nc_u32_e32 v3, v3, v0
216 ; GFX10-NEXT:    v_mov_b32_e32 v0, 0
217 ; GFX10-NEXT:    global_store_dwordx2 v0, v[2:3], s[4:5]
218 ; GFX10-NEXT:    s_endpgm
220 ; GFX11-LABEL: v_mul_i64_masked_src0_hi:
221 ; GFX11:       ; %bb.0:
222 ; GFX11-NEXT:    s_clause 0x1
223 ; GFX11-NEXT:    s_load_b128 s[4:7], s[0:1], 0x24
224 ; GFX11-NEXT:    s_load_b64 s[0:1], s[0:1], 0x34
225 ; GFX11-NEXT:    v_lshlrev_b32_e32 v0, 3, v0
226 ; GFX11-NEXT:    s_waitcnt lgkmcnt(0)
227 ; GFX11-NEXT:    s_clause 0x1
228 ; GFX11-NEXT:    global_load_b32 v4, v0, s[6:7]
229 ; GFX11-NEXT:    global_load_b64 v[0:1], v0, s[0:1]
230 ; GFX11-NEXT:    s_waitcnt vmcnt(0)
231 ; GFX11-NEXT:    v_mad_u64_u32 v[2:3], null, v4, v0, 0
232 ; GFX11-NEXT:    v_mul_lo_u32 v0, v4, v1
233 ; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1)
234 ; GFX11-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_add_nc_u32 v3, v3, v0
235 ; GFX11-NEXT:    global_store_b64 v0, v[2:3], s[4:5]
236 ; GFX11-NEXT:    s_nop 0
237 ; GFX11-NEXT:    s_sendmsg sendmsg(MSG_DEALLOC_VGPRS)
238 ; GFX11-NEXT:    s_endpgm
239  %tid = call i32 @llvm.amdgcn.workitem.id.x()
240   %gep.a = getelementptr inbounds i64, ptr addrspace(1) %aptr, i32 %tid
241   %gep.b = getelementptr inbounds i64, ptr addrspace(1) %bptr, i32 %tid
242   %a = load i64, ptr addrspace(1) %gep.a
243   %b = load i64, ptr addrspace(1) %gep.b
244   %a_and = and i64 %a, u0x00000000FFFFFFFF
245   %mul = mul i64 %a_and, %b
246   store i64 %mul, ptr addrspace(1) %out
247   ret void
250 ; 64-bit multiplication where lower bytes of first argument were masked.
251 define amdgpu_kernel void @v_mul_i64_masked_src0_lo(ptr addrspace(1) %out, ptr addrspace(1) %aptr, ptr addrspace(1) %bptr) {
252 ; GFX10-LABEL: v_mul_i64_masked_src0_lo:
253 ; GFX10:       ; %bb.0:
254 ; GFX10-NEXT:    s_clause 0x1
255 ; GFX10-NEXT:    s_load_dwordx4 s[4:7], s[0:1], 0x24
256 ; GFX10-NEXT:    s_load_dwordx2 s[2:3], s[0:1], 0x34
257 ; GFX10-NEXT:    v_lshlrev_b32_e32 v4, 3, v0
258 ; GFX10-NEXT:    s_waitcnt lgkmcnt(0)
259 ; GFX10-NEXT:    s_clause 0x1
260 ; GFX10-NEXT:    global_load_dwordx2 v[0:1], v4, s[6:7]
261 ; GFX10-NEXT:    global_load_dwordx2 v[2:3], v4, s[2:3]
262 ; GFX10-NEXT:    s_waitcnt vmcnt(1)
263 ; GFX10-NEXT:    v_mov_b32_e32 v0, 0
264 ; GFX10-NEXT:    s_waitcnt vmcnt(0)
265 ; GFX10-NEXT:    v_mul_lo_u32 v1, v1, v2
266 ; GFX10-NEXT:    global_store_dwordx2 v0, v[0:1], s[4:5]
267 ; GFX10-NEXT:    s_endpgm
269 ; GFX11-LABEL: v_mul_i64_masked_src0_lo:
270 ; GFX11:       ; %bb.0:
271 ; GFX11-NEXT:    s_clause 0x1
272 ; GFX11-NEXT:    s_load_b128 s[4:7], s[0:1], 0x24
273 ; GFX11-NEXT:    s_load_b64 s[0:1], s[0:1], 0x34
274 ; GFX11-NEXT:    v_lshlrev_b32_e32 v2, 3, v0
275 ; GFX11-NEXT:    s_waitcnt lgkmcnt(0)
276 ; GFX11-NEXT:    s_clause 0x1
277 ; GFX11-NEXT:    global_load_b64 v[0:1], v2, s[6:7]
278 ; GFX11-NEXT:    global_load_b64 v[2:3], v2, s[0:1]
279 ; GFX11-NEXT:    s_waitcnt vmcnt(1)
280 ; GFX11-NEXT:    v_mov_b32_e32 v0, 0
281 ; GFX11-NEXT:    s_waitcnt vmcnt(0)
282 ; GFX11-NEXT:    v_mul_lo_u32 v1, v1, v2
283 ; GFX11-NEXT:    global_store_b64 v0, v[0:1], s[4:5]
284 ; GFX11-NEXT:    s_nop 0
285 ; GFX11-NEXT:    s_sendmsg sendmsg(MSG_DEALLOC_VGPRS)
286 ; GFX11-NEXT:    s_endpgm
287   %tid = call i32 @llvm.amdgcn.workitem.id.x()
288   %gep.a = getelementptr inbounds i64, ptr addrspace(1) %aptr, i32 %tid
289   %gep.b = getelementptr inbounds i64, ptr addrspace(1) %bptr, i32 %tid
290   %a = load i64, ptr addrspace(1) %gep.a
291   %b = load i64, ptr addrspace(1) %gep.b
292   %a_and = and i64 %a, u0xFFFFFFFF00000000
293   %mul = mul i64 %a_and, %b
294   store i64 %mul, ptr addrspace(1) %out
295   ret void
298 ; 64-bit multiplication where the lower bytes of the second argument were masked.
299 define amdgpu_kernel void @v_mul_i64_masked_src1_lo(ptr addrspace(1) %out, ptr addrspace(1) %aptr, ptr addrspace(1) %bptr) {
300 ; GFX10-LABEL: v_mul_i64_masked_src1_lo:
301 ; GFX10:       ; %bb.0:
302 ; GFX10-NEXT:    s_clause 0x1
303 ; GFX10-NEXT:    s_load_dwordx4 s[4:7], s[0:1], 0x24
304 ; GFX10-NEXT:    s_load_dwordx2 s[2:3], s[0:1], 0x34
305 ; GFX10-NEXT:    v_lshlrev_b32_e32 v3, 3, v0
306 ; GFX10-NEXT:    ; kill: killed $vgpr3
307 ; GFX10-NEXT:    ; kill: killed $sgpr6_sgpr7
308 ; GFX10-NEXT:    s_waitcnt lgkmcnt(0)
309 ; GFX10-NEXT:    s_clause 0x1
310 ; GFX10-NEXT:    global_load_dwordx2 v[0:1], v3, s[6:7]
311 ; GFX10-NEXT:    global_load_dwordx2 v[1:2], v3, s[2:3]
312 ; GFX10-NEXT:    ; kill: killed $sgpr2_sgpr3
313 ; GFX10-NEXT:    s_waitcnt vmcnt(0)
314 ; GFX10-NEXT:    v_mul_lo_u32 v1, v0, v2
315 ; GFX10-NEXT:    v_mov_b32_e32 v0, 0
316 ; GFX10-NEXT:    global_store_dwordx2 v0, v[0:1], s[4:5]
317 ; GFX10-NEXT:    s_endpgm
319 ; GFX11-LABEL: v_mul_i64_masked_src1_lo:
320 ; GFX11:       ; %bb.0:
321 ; GFX11-NEXT:    s_clause 0x1
322 ; GFX11-NEXT:    s_load_b128 s[4:7], s[0:1], 0x24
323 ; GFX11-NEXT:    s_load_b64 s[0:1], s[0:1], 0x34
324 ; GFX11-NEXT:    v_lshlrev_b32_e32 v2, 3, v0
325 ; GFX11-NEXT:    s_waitcnt lgkmcnt(0)
326 ; GFX11-NEXT:    s_clause 0x1
327 ; GFX11-NEXT:    global_load_b64 v[0:1], v2, s[6:7]
328 ; GFX11-NEXT:    global_load_b64 v[1:2], v2, s[0:1]
329 ; GFX11-NEXT:    s_waitcnt vmcnt(0)
330 ; GFX11-NEXT:    v_mul_lo_u32 v1, v0, v2
331 ; GFX11-NEXT:    v_mov_b32_e32 v0, 0
332 ; GFX11-NEXT:    global_store_b64 v0, v[0:1], s[4:5]
333 ; GFX11-NEXT:    s_nop 0
334 ; GFX11-NEXT:    s_sendmsg sendmsg(MSG_DEALLOC_VGPRS)
335 ; GFX11-NEXT:    s_endpgm
336   %tid = call i32 @llvm.amdgcn.workitem.id.x()
337   %gep.a = getelementptr inbounds i64, ptr addrspace(1) %aptr, i32 %tid
338   %gep.b = getelementptr inbounds i64, ptr addrspace(1) %bptr, i32 %tid
339   %a = load i64, ptr addrspace(1) %gep.a
340   %b = load i64, ptr addrspace(1) %gep.b
341   %b_and = and i64 %b, u0xFFFFFFFF00000000
342   %mul = mul i64 %a, %b_and
343   store i64 %mul, ptr addrspace(1) %out
344   ret void
347 ; 64-bit multiplication where the entire first argument is masked.
348 define amdgpu_kernel void @v_mul_i64_masked_src0(ptr addrspace(1) %out, ptr addrspace(1) %aptr, ptr addrspace(1) %bptr) {
349 ; GFX10-LABEL: v_mul_i64_masked_src0:
350 ; GFX10:       ; %bb.0:
351 ; GFX10-NEXT:    s_load_dwordx2 s[0:1], s[0:1], 0x24
352 ; GFX10-NEXT:    v_mov_b32_e32 v0, 0
353 ; GFX10-NEXT:    v_mov_b32_e32 v1, 0
354 ; GFX10-NEXT:    v_mov_b32_e32 v2, 0
355 ; GFX10-NEXT:    s_waitcnt lgkmcnt(0)
356 ; GFX10-NEXT:    global_store_dwordx2 v2, v[0:1], s[0:1]
357 ; GFX10-NEXT:    s_endpgm
359 ; GFX11-LABEL: v_mul_i64_masked_src0:
360 ; GFX11:       ; %bb.0:
361 ; GFX11-NEXT:    s_load_b64 s[0:1], s[0:1], 0x24
362 ; GFX11-NEXT:    v_mov_b32_e32 v0, 0
363 ; GFX11-NEXT:    v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, 0
364 ; GFX11-NEXT:    s_waitcnt lgkmcnt(0)
365 ; GFX11-NEXT:    global_store_b64 v2, v[0:1], s[0:1]
366 ; GFX11-NEXT:    s_nop 0
367 ; GFX11-NEXT:    s_sendmsg sendmsg(MSG_DEALLOC_VGPRS)
368 ; GFX11-NEXT:    s_endpgm
369   %tid = call i32 @llvm.amdgcn.workitem.id.x()
370   %gep.a = getelementptr inbounds i64, ptr addrspace(1) %aptr, i32 %tid
371   %gep.b = getelementptr inbounds i64, ptr addrspace(1) %bptr, i32 %tid
372   %a = load i64, ptr addrspace(1) %gep.a
373   %b = load i64, ptr addrspace(1) %gep.b
374   %a_and = and i64 %a, u0x0000000000000000
375   %mul = mul i64 %a_and, %b
376   store i64 %mul, ptr addrspace(1) %out
377   ret void
380 ; 64-bit multiplication where the parts of the high and low bytes of the first argument are masked.
381 define amdgpu_kernel void @v_mul_i64_partially_masked_src0(ptr addrspace(1) %out, ptr addrspace(1) %aptr, ptr addrspace(1) %bptr) {
382 ; GFX10-LABEL: v_mul_i64_partially_masked_src0:
383 ; GFX10:       ; %bb.0:
384 ; GFX10-NEXT:    s_clause 0x1
385 ; GFX10-NEXT:    s_load_dwordx4 s[4:7], s[0:1], 0x24
386 ; GFX10-NEXT:    s_load_dwordx2 s[2:3], s[0:1], 0x34
387 ; GFX10-NEXT:    v_lshlrev_b32_e32 v4, 3, v0
388 ; GFX10-NEXT:    s_waitcnt lgkmcnt(0)
389 ; GFX10-NEXT:    s_clause 0x1
390 ; GFX10-NEXT:    global_load_dwordx2 v[0:1], v4, s[6:7]
391 ; GFX10-NEXT:    global_load_dwordx2 v[2:3], v4, s[2:3]
392 ; GFX10-NEXT:    s_waitcnt vmcnt(1)
393 ; GFX10-NEXT:    v_and_b32_e32 v4, 0xfff00000, v0
394 ; GFX10-NEXT:    v_and_b32_e32 v5, 0xf00f, v1
395 ; GFX10-NEXT:    s_waitcnt vmcnt(0)
396 ; GFX10-NEXT:    v_mad_u64_u32 v[0:1], s0, v4, v2, 0
397 ; GFX10-NEXT:    v_mul_lo_u32 v3, v4, v3
398 ; GFX10-NEXT:    v_mul_lo_u32 v2, v5, v2
399 ; GFX10-NEXT:    v_add3_u32 v1, v1, v3, v2
400 ; GFX10-NEXT:    v_mov_b32_e32 v2, 0
401 ; GFX10-NEXT:    global_store_dwordx2 v2, v[0:1], s[4:5]
402 ; GFX10-NEXT:    s_endpgm
404 ; GFX11-LABEL: v_mul_i64_partially_masked_src0:
405 ; GFX11:       ; %bb.0:
406 ; GFX11-NEXT:    s_clause 0x1
407 ; GFX11-NEXT:    s_load_b128 s[4:7], s[0:1], 0x24
408 ; GFX11-NEXT:    s_load_b64 s[0:1], s[0:1], 0x34
409 ; GFX11-NEXT:    v_lshlrev_b32_e32 v2, 3, v0
410 ; GFX11-NEXT:    s_waitcnt lgkmcnt(0)
411 ; GFX11-NEXT:    s_clause 0x1
412 ; GFX11-NEXT:    global_load_b64 v[0:1], v2, s[6:7]
413 ; GFX11-NEXT:    global_load_b64 v[2:3], v2, s[0:1]
414 ; GFX11-NEXT:    s_waitcnt vmcnt(1)
415 ; GFX11-NEXT:    v_and_b32_e32 v4, 0xfff00000, v0
416 ; GFX11-NEXT:    v_and_b32_e32 v5, 0xf00f, v1
417 ; GFX11-NEXT:    s_waitcnt vmcnt(0)
418 ; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_2) | instskip(SKIP_1) | instid1(VALU_DEP_3)
419 ; GFX11-NEXT:    v_mad_u64_u32 v[0:1], null, v4, v2, 0
420 ; GFX11-NEXT:    v_mul_lo_u32 v3, v4, v3
421 ; GFX11-NEXT:    v_mul_lo_u32 v2, v5, v2
422 ; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1)
423 ; GFX11-NEXT:    v_add3_u32 v1, v1, v3, v2
424 ; GFX11-NEXT:    v_mov_b32_e32 v2, 0
425 ; GFX11-NEXT:    global_store_b64 v2, v[0:1], s[4:5]
426 ; GFX11-NEXT:    s_nop 0
427 ; GFX11-NEXT:    s_sendmsg sendmsg(MSG_DEALLOC_VGPRS)
428 ; GFX11-NEXT:    s_endpgm
429   %tid = call i32 @llvm.amdgcn.workitem.id.x()
430   %gep.a = getelementptr inbounds i64, ptr addrspace(1) %aptr, i32 %tid
431   %gep.b = getelementptr inbounds i64, ptr addrspace(1) %bptr, i32 %tid
432   %a = load i64, ptr addrspace(1) %gep.a
433   %b = load i64, ptr addrspace(1) %gep.b
434   %a_and = and i64 %a, u0x0000F00FFFF00000
435   %mul = mul i64 %a_and, %b
436   store i64 %mul, ptr addrspace(1) %out
437   ret void
440 ; 64-bit multiplication, where the first argument is masked before a branch
441 define amdgpu_kernel void @v_mul64_masked_before_branch(ptr addrspace(1) %out, ptr addrspace(1) %aptr, ptr addrspace(1) %bptr) {
442 ; GFX10-LABEL: v_mul64_masked_before_branch:
443 ; GFX10:       ; %bb.0: ; %entry
444 ; GFX10-NEXT:    s_load_dwordx2 s[0:1], s[0:1], 0x24
445 ; GFX10-NEXT:    v_mov_b32_e32 v0, 0
446 ; GFX10-NEXT:    v_mov_b32_e32 v1, 0
447 ; GFX10-NEXT:    v_mov_b32_e32 v2, 0
448 ; GFX10-NEXT:    s_waitcnt lgkmcnt(0)
449 ; GFX10-NEXT:    global_store_dwordx2 v2, v[0:1], s[0:1]
450 ; GFX10-NEXT:    s_endpgm
452 ; GFX11-LABEL: v_mul64_masked_before_branch:
453 ; GFX11:       ; %bb.0: ; %entry
454 ; GFX11-NEXT:    s_load_b64 s[0:1], s[0:1], 0x24
455 ; GFX11-NEXT:    v_mov_b32_e32 v0, 0
456 ; GFX11-NEXT:    v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, 0
457 ; GFX11-NEXT:    s_waitcnt lgkmcnt(0)
458 ; GFX11-NEXT:    global_store_b64 v2, v[0:1], s[0:1]
459 ; GFX11-NEXT:    s_nop 0
460 ; GFX11-NEXT:    s_sendmsg sendmsg(MSG_DEALLOC_VGPRS)
461 ; GFX11-NEXT:    s_endpgm
462 entry:
463   %tid = call i32 @llvm.amdgcn.workitem.id.x()
464   %gep.a = getelementptr inbounds i64, ptr addrspace(1) %aptr, i32 %tid
465   %gep.b = getelementptr inbounds i64, ptr addrspace(1) %bptr, i32 %tid
466   %a = load i64, ptr addrspace(1) %gep.a
467   %b = load i64, ptr addrspace(1) %gep.b
468   %a_and = and i64 %a, u0x0000000000000000
469   %0 = icmp eq i64 %b, 0
470   br i1 %0, label %if, label %else
473   %b_and = and i64 %b, u0xFFFFFFFF00000000
474   %1 = mul i64 %a_and, %b_and
475   br label %endif
477 else:
478   %2 = mul i64 %a_and, %b
479   br label %endif
481 endif:
482   %3 = phi i64 [%1, %if], [%2, %else]
483   store i64 %3, ptr addrspace(1) %out
484   ret void
487 ; 64-bit multiplication with both arguments changed in different basic blocks.
488 define amdgpu_kernel void @v_mul64_masked_before_and_in_branch(ptr addrspace(1) %out, ptr addrspace(1) %aptr, ptr addrspace(1) %bptr) {
489 ; GFX10-LABEL: v_mul64_masked_before_and_in_branch:
490 ; GFX10:       ; %bb.0: ; %entry
491 ; GFX10-NEXT:    s_clause 0x1
492 ; GFX10-NEXT:    s_load_dwordx4 s[4:7], s[0:1], 0x24
493 ; GFX10-NEXT:    s_load_dwordx2 s[2:3], s[0:1], 0x34
494 ; GFX10-NEXT:    v_lshlrev_b32_e32 v4, 3, v0
495 ; GFX10-NEXT:    s_waitcnt lgkmcnt(0)
496 ; GFX10-NEXT:    s_clause 0x1
497 ; GFX10-NEXT:    global_load_dwordx2 v[2:3], v4, s[6:7]
498 ; GFX10-NEXT:    global_load_dwordx2 v[0:1], v4, s[2:3]
499 ; GFX10-NEXT:    s_waitcnt vmcnt(1)
500 ; GFX10-NEXT:    v_cmp_ge_u64_e32 vcc_lo, 0, v[2:3]
501 ; GFX10-NEXT:    s_waitcnt vmcnt(0)
502 ; GFX10-NEXT:    v_mul_lo_u32 v1, v2, v1
503 ; GFX10-NEXT:    s_and_saveexec_b32 s0, vcc_lo
504 ; GFX10-NEXT:    s_xor_b32 s0, exec_lo, s0
505 ; GFX10-NEXT:  ; %bb.1: ; %else
506 ; GFX10-NEXT:    v_mad_u64_u32 v[2:3], s1, v2, v0, 0
507 ; GFX10-NEXT:    v_add_nc_u32_e32 v3, v3, v1
508 ; GFX10-NEXT:    v_mov_b32_e32 v0, v2
509 ; GFX10-NEXT:    v_mov_b32_e32 v1, v3
510 ; GFX10-NEXT:  ; %bb.2: ; %Flow
511 ; GFX10-NEXT:    s_andn2_saveexec_b32 s0, s0
512 ; GFX10-NEXT:  ; %bb.3: ; %if
513 ; GFX10-NEXT:    v_mov_b32_e32 v0, 0
514 ; GFX10-NEXT:  ; %bb.4: ; %endif
515 ; GFX10-NEXT:    s_or_b32 exec_lo, exec_lo, s0
516 ; GFX10-NEXT:    v_mov_b32_e32 v2, 0
517 ; GFX10-NEXT:    global_store_dwordx2 v2, v[0:1], s[4:5]
518 ; GFX10-NEXT:    s_endpgm
520 ; GFX11-LABEL: v_mul64_masked_before_and_in_branch:
521 ; GFX11:       ; %bb.0: ; %entry
522 ; GFX11-NEXT:    s_clause 0x1
523 ; GFX11-NEXT:    s_load_b128 s[4:7], s[0:1], 0x24
524 ; GFX11-NEXT:    s_load_b64 s[0:1], s[0:1], 0x34
525 ; GFX11-NEXT:    v_lshlrev_b32_e32 v0, 3, v0
526 ; GFX11-NEXT:    s_waitcnt lgkmcnt(0)
527 ; GFX11-NEXT:    s_clause 0x1
528 ; GFX11-NEXT:    global_load_b64 v[2:3], v0, s[6:7]
529 ; GFX11-NEXT:    global_load_b64 v[0:1], v0, s[0:1]
530 ; GFX11-NEXT:    s_mov_b32 s0, exec_lo
531 ; GFX11-NEXT:    s_waitcnt vmcnt(0)
532 ; GFX11-NEXT:    v_mul_lo_u32 v1, v2, v1
533 ; GFX11-NEXT:    v_cmpx_ge_u64_e32 0, v[2:3]
534 ; GFX11-NEXT:    s_xor_b32 s0, exec_lo, s0
535 ; GFX11-NEXT:  ; %bb.1: ; %else
536 ; GFX11-NEXT:    v_mad_u64_u32 v[2:3], null, v2, v0, 0
537 ; GFX11-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
538 ; GFX11-NEXT:    v_add_nc_u32_e32 v3, v3, v1
539 ; GFX11-NEXT:    v_dual_mov_b32 v0, v2 :: v_dual_mov_b32 v1, v3
540 ; GFX11-NEXT:  ; %bb.2: ; %Flow
541 ; GFX11-NEXT:    s_and_not1_saveexec_b32 s0, s0
542 ; GFX11-NEXT:  ; %bb.3: ; %if
543 ; GFX11-NEXT:    v_mov_b32_e32 v0, 0
544 ; GFX11-NEXT:  ; %bb.4: ; %endif
545 ; GFX11-NEXT:    s_or_b32 exec_lo, exec_lo, s0
546 ; GFX11-NEXT:    v_mov_b32_e32 v2, 0
547 ; GFX11-NEXT:    global_store_b64 v2, v[0:1], s[4:5]
548 ; GFX11-NEXT:    s_nop 0
549 ; GFX11-NEXT:    s_sendmsg sendmsg(MSG_DEALLOC_VGPRS)
550 ; GFX11-NEXT:    s_endpgm
551 entry:
552   %tid = call i32 @llvm.amdgcn.workitem.id.x()
553   %gep.a = getelementptr inbounds i64, ptr addrspace(1) %aptr, i32 %tid
554   %gep.b = getelementptr inbounds i64, ptr addrspace(1) %bptr, i32 %tid
555   %a = load i64, ptr addrspace(1) %gep.a
556   %b = load i64, ptr addrspace(1) %gep.b
557   %a_and = and i64 %a, u0x00000000FFFFFFFF
558   %0 = icmp ugt i64 %a, 0
559   br i1 %0, label %if, label %else
562   %b_and = and i64 %b, u0xFFFFFFFF00000000
563   %1 = mul i64 %a_and, %b_and
564   br label %endif
566 else:
567   %2 = mul i64 %a_and, %b
568   br label %endif
570 endif:
571   %3 = phi i64 [%1, %if], [%2, %else]
572   store i64 %3, ptr addrspace(1) %out
573   ret void