xref: /llvm-project/llvm/test/CodeGen/LoongArch/ctlz-cttz-ctpop.ll (revision 1897bf61f0bc85c8637997d0f2aa7d94d375d787)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc --mtriple=loongarch32 -mattr=+d < %s | FileCheck %s --check-prefix=LA32
3; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s --check-prefix=LA64
4
5declare i8 @llvm.ctlz.i8(i8, i1)
6declare i16 @llvm.ctlz.i16(i16, i1)
7declare i32 @llvm.ctlz.i32(i32, i1)
8declare i64 @llvm.ctlz.i64(i64, i1)
9declare i8 @llvm.ctpop.i8(i8)
10declare i16 @llvm.ctpop.i16(i16)
11declare i32 @llvm.ctpop.i32(i32)
12declare i64 @llvm.ctpop.i64(i64)
13declare i8 @llvm.cttz.i8(i8, i1)
14declare i16 @llvm.cttz.i16(i16, i1)
15declare i32 @llvm.cttz.i32(i32, i1)
16declare i64 @llvm.cttz.i64(i64, i1)
17
18define i8 @test_ctlz_i8(i8 %a) nounwind {
19; LA32-LABEL: test_ctlz_i8:
20; LA32:       # %bb.0:
21; LA32-NEXT:    andi $a0, $a0, 255
22; LA32-NEXT:    clz.w $a0, $a0
23; LA32-NEXT:    addi.w $a0, $a0, -24
24; LA32-NEXT:    ret
25;
26; LA64-LABEL: test_ctlz_i8:
27; LA64:       # %bb.0:
28; LA64-NEXT:    andi $a0, $a0, 255
29; LA64-NEXT:    clz.d $a0, $a0
30; LA64-NEXT:    addi.d $a0, $a0, -56
31; LA64-NEXT:    ret
32  %tmp = call i8 @llvm.ctlz.i8(i8 %a, i1 false)
33  ret i8 %tmp
34}
35
36define i16 @test_ctlz_i16(i16 %a) nounwind {
37; LA32-LABEL: test_ctlz_i16:
38; LA32:       # %bb.0:
39; LA32-NEXT:    bstrpick.w $a0, $a0, 15, 0
40; LA32-NEXT:    clz.w $a0, $a0
41; LA32-NEXT:    addi.w $a0, $a0, -16
42; LA32-NEXT:    ret
43;
44; LA64-LABEL: test_ctlz_i16:
45; LA64:       # %bb.0:
46; LA64-NEXT:    bstrpick.d $a0, $a0, 15, 0
47; LA64-NEXT:    clz.d $a0, $a0
48; LA64-NEXT:    addi.d $a0, $a0, -48
49; LA64-NEXT:    ret
50  %tmp = call i16 @llvm.ctlz.i16(i16 %a, i1 false)
51  ret i16 %tmp
52}
53
54define i32 @test_ctlz_i32(i32 %a) nounwind {
55; LA32-LABEL: test_ctlz_i32:
56; LA32:       # %bb.0:
57; LA32-NEXT:    clz.w $a0, $a0
58; LA32-NEXT:    ret
59;
60; LA64-LABEL: test_ctlz_i32:
61; LA64:       # %bb.0:
62; LA64-NEXT:    clz.w $a0, $a0
63; LA64-NEXT:    ret
64  %tmp = call i32 @llvm.ctlz.i32(i32 %a, i1 false)
65  ret i32 %tmp
66}
67
68define i64 @test_ctlz_i64(i64 %a) nounwind {
69; LA32-LABEL: test_ctlz_i64:
70; LA32:       # %bb.0:
71; LA32-NEXT:    sltu $a2, $zero, $a1
72; LA32-NEXT:    clz.w $a1, $a1
73; LA32-NEXT:    maskeqz $a1, $a1, $a2
74; LA32-NEXT:    clz.w $a0, $a0
75; LA32-NEXT:    addi.w $a0, $a0, 32
76; LA32-NEXT:    masknez $a0, $a0, $a2
77; LA32-NEXT:    or $a0, $a1, $a0
78; LA32-NEXT:    move $a1, $zero
79; LA32-NEXT:    ret
80;
81; LA64-LABEL: test_ctlz_i64:
82; LA64:       # %bb.0:
83; LA64-NEXT:    clz.d $a0, $a0
84; LA64-NEXT:    ret
85  %tmp = call i64 @llvm.ctlz.i64(i64 %a, i1 false)
86  ret i64 %tmp
87}
88
89define i8 @test_not_ctlz_i8(i8 %a) nounwind {
90; LA32-LABEL: test_not_ctlz_i8:
91; LA32:       # %bb.0:
92; LA32-NEXT:    slli.w $a0, $a0, 24
93; LA32-NEXT:    clo.w $a0, $a0
94; LA32-NEXT:    ret
95;
96; LA64-LABEL: test_not_ctlz_i8:
97; LA64:       # %bb.0:
98; LA64-NEXT:    slli.d $a0, $a0, 56
99; LA64-NEXT:    clo.d $a0, $a0
100; LA64-NEXT:    ret
101  %neg = xor i8 %a, -1
102  %tmp = call i8 @llvm.ctlz.i8(i8 %neg, i1 false)
103  ret i8 %tmp
104}
105
106define i16 @test_not_ctlz_i16(i16 %a) nounwind {
107; LA32-LABEL: test_not_ctlz_i16:
108; LA32:       # %bb.0:
109; LA32-NEXT:    slli.w $a0, $a0, 16
110; LA32-NEXT:    clo.w $a0, $a0
111; LA32-NEXT:    ret
112;
113; LA64-LABEL: test_not_ctlz_i16:
114; LA64:       # %bb.0:
115; LA64-NEXT:    slli.d $a0, $a0, 48
116; LA64-NEXT:    clo.d $a0, $a0
117; LA64-NEXT:    ret
118  %neg = xor i16 %a, -1
119  %tmp = call i16 @llvm.ctlz.i16(i16 %neg, i1 false)
120  ret i16 %tmp
121}
122
123define i32 @test_not_ctlz_i32(i32 %a) nounwind {
124; LA32-LABEL: test_not_ctlz_i32:
125; LA32:       # %bb.0:
126; LA32-NEXT:    clo.w $a0, $a0
127; LA32-NEXT:    ret
128;
129; LA64-LABEL: test_not_ctlz_i32:
130; LA64:       # %bb.0:
131; LA64-NEXT:    clo.w $a0, $a0
132; LA64-NEXT:    ret
133  %neg = xor i32 %a, -1
134  %tmp = call i32 @llvm.ctlz.i32(i32 %neg, i1 false)
135  ret i32 %tmp
136}
137
138define i64 @test_not_ctlz_i64(i64 %a) nounwind {
139; LA32-LABEL: test_not_ctlz_i64:
140; LA32:       # %bb.0:
141; LA32-NEXT:    nor $a2, $a1, $zero
142; LA32-NEXT:    sltu $a2, $zero, $a2
143; LA32-NEXT:    clo.w $a0, $a0
144; LA32-NEXT:    addi.w $a0, $a0, 32
145; LA32-NEXT:    masknez $a0, $a0, $a2
146; LA32-NEXT:    clo.w $a1, $a1
147; LA32-NEXT:    maskeqz $a1, $a1, $a2
148; LA32-NEXT:    or $a0, $a1, $a0
149; LA32-NEXT:    move $a1, $zero
150; LA32-NEXT:    ret
151;
152; LA64-LABEL: test_not_ctlz_i64:
153; LA64:       # %bb.0:
154; LA64-NEXT:    clo.d $a0, $a0
155; LA64-NEXT:    ret
156  %neg = xor i64 %a, -1
157  %tmp = call i64 @llvm.ctlz.i64(i64 %neg, i1 false)
158  ret i64 %tmp
159}
160
161define i8 @test_ctpop_i8(i8 %a) nounwind {
162; LA32-LABEL: test_ctpop_i8:
163; LA32:       # %bb.0:
164; LA32-NEXT:    srli.w $a1, $a0, 1
165; LA32-NEXT:    andi $a1, $a1, 85
166; LA32-NEXT:    sub.w $a0, $a0, $a1
167; LA32-NEXT:    andi $a1, $a0, 51
168; LA32-NEXT:    srli.w $a0, $a0, 2
169; LA32-NEXT:    andi $a0, $a0, 51
170; LA32-NEXT:    add.w $a0, $a1, $a0
171; LA32-NEXT:    srli.w $a1, $a0, 4
172; LA32-NEXT:    add.w $a0, $a0, $a1
173; LA32-NEXT:    andi $a0, $a0, 15
174; LA32-NEXT:    ret
175;
176; LA64-LABEL: test_ctpop_i8:
177; LA64:       # %bb.0:
178; LA64-NEXT:    andi $a0, $a0, 255
179; LA64-NEXT:    vldi $vr0, 0
180; LA64-NEXT:    vinsgr2vr.d $vr0, $a0, 0
181; LA64-NEXT:    vpcnt.d $vr0, $vr0
182; LA64-NEXT:    vpickve2gr.d $a0, $vr0, 0
183; LA64-NEXT:    ret
184  %1 = call i8 @llvm.ctpop.i8(i8 %a)
185  ret i8 %1
186}
187
188define i16 @test_ctpop_i16(i16 %a) nounwind {
189; LA32-LABEL: test_ctpop_i16:
190; LA32:       # %bb.0:
191; LA32-NEXT:    srli.w $a1, $a0, 1
192; LA32-NEXT:    lu12i.w $a2, 5
193; LA32-NEXT:    ori $a2, $a2, 1365
194; LA32-NEXT:    and $a1, $a1, $a2
195; LA32-NEXT:    sub.w $a0, $a0, $a1
196; LA32-NEXT:    lu12i.w $a1, 3
197; LA32-NEXT:    ori $a1, $a1, 819
198; LA32-NEXT:    and $a2, $a0, $a1
199; LA32-NEXT:    srli.w $a0, $a0, 2
200; LA32-NEXT:    and $a0, $a0, $a1
201; LA32-NEXT:    add.w $a0, $a2, $a0
202; LA32-NEXT:    srli.w $a1, $a0, 4
203; LA32-NEXT:    add.w $a0, $a0, $a1
204; LA32-NEXT:    bstrpick.w $a1, $a0, 11, 8
205; LA32-NEXT:    andi $a0, $a0, 15
206; LA32-NEXT:    add.w $a0, $a0, $a1
207; LA32-NEXT:    ret
208;
209; LA64-LABEL: test_ctpop_i16:
210; LA64:       # %bb.0:
211; LA64-NEXT:    bstrpick.d $a0, $a0, 15, 0
212; LA64-NEXT:    vldi $vr0, 0
213; LA64-NEXT:    vinsgr2vr.d $vr0, $a0, 0
214; LA64-NEXT:    vpcnt.d $vr0, $vr0
215; LA64-NEXT:    vpickve2gr.d $a0, $vr0, 0
216; LA64-NEXT:    ret
217  %1 = call i16 @llvm.ctpop.i16(i16 %a)
218  ret i16 %1
219}
220
221define i32 @test_ctpop_i32(i32 %a) nounwind {
222; LA32-LABEL: test_ctpop_i32:
223; LA32:       # %bb.0:
224; LA32-NEXT:    srli.w $a1, $a0, 1
225; LA32-NEXT:    lu12i.w $a2, 349525
226; LA32-NEXT:    ori $a2, $a2, 1365
227; LA32-NEXT:    and $a1, $a1, $a2
228; LA32-NEXT:    sub.w $a0, $a0, $a1
229; LA32-NEXT:    lu12i.w $a1, 209715
230; LA32-NEXT:    ori $a1, $a1, 819
231; LA32-NEXT:    and $a2, $a0, $a1
232; LA32-NEXT:    srli.w $a0, $a0, 2
233; LA32-NEXT:    and $a0, $a0, $a1
234; LA32-NEXT:    add.w $a0, $a2, $a0
235; LA32-NEXT:    srli.w $a1, $a0, 4
236; LA32-NEXT:    add.w $a0, $a0, $a1
237; LA32-NEXT:    lu12i.w $a1, 61680
238; LA32-NEXT:    ori $a1, $a1, 3855
239; LA32-NEXT:    and $a0, $a0, $a1
240; LA32-NEXT:    lu12i.w $a1, 4112
241; LA32-NEXT:    ori $a1, $a1, 257
242; LA32-NEXT:    mul.w $a0, $a0, $a1
243; LA32-NEXT:    srli.w $a0, $a0, 24
244; LA32-NEXT:    ret
245;
246; LA64-LABEL: test_ctpop_i32:
247; LA64:       # %bb.0:
248; LA64-NEXT:    bstrpick.d $a0, $a0, 31, 0
249; LA64-NEXT:    vldi $vr0, 0
250; LA64-NEXT:    vinsgr2vr.d $vr0, $a0, 0
251; LA64-NEXT:    vpcnt.d $vr0, $vr0
252; LA64-NEXT:    vpickve2gr.d $a0, $vr0, 0
253; LA64-NEXT:    ret
254  %1 = call i32 @llvm.ctpop.i32(i32 %a)
255  ret i32 %1
256}
257
258define i64 @test_ctpop_i64(i64 %a) nounwind {
259; LA32-LABEL: test_ctpop_i64:
260; LA32:       # %bb.0:
261; LA32-NEXT:    srli.w $a2, $a1, 1
262; LA32-NEXT:    lu12i.w $a3, 349525
263; LA32-NEXT:    ori $a3, $a3, 1365
264; LA32-NEXT:    and $a2, $a2, $a3
265; LA32-NEXT:    sub.w $a1, $a1, $a2
266; LA32-NEXT:    lu12i.w $a2, 209715
267; LA32-NEXT:    ori $a2, $a2, 819
268; LA32-NEXT:    and $a4, $a1, $a2
269; LA32-NEXT:    srli.w $a1, $a1, 2
270; LA32-NEXT:    and $a1, $a1, $a2
271; LA32-NEXT:    add.w $a1, $a4, $a1
272; LA32-NEXT:    srli.w $a4, $a1, 4
273; LA32-NEXT:    add.w $a1, $a1, $a4
274; LA32-NEXT:    lu12i.w $a4, 61680
275; LA32-NEXT:    ori $a4, $a4, 3855
276; LA32-NEXT:    and $a1, $a1, $a4
277; LA32-NEXT:    lu12i.w $a5, 4112
278; LA32-NEXT:    ori $a5, $a5, 257
279; LA32-NEXT:    mul.w $a1, $a1, $a5
280; LA32-NEXT:    srli.w $a1, $a1, 24
281; LA32-NEXT:    srli.w $a6, $a0, 1
282; LA32-NEXT:    and $a3, $a6, $a3
283; LA32-NEXT:    sub.w $a0, $a0, $a3
284; LA32-NEXT:    and $a3, $a0, $a2
285; LA32-NEXT:    srli.w $a0, $a0, 2
286; LA32-NEXT:    and $a0, $a0, $a2
287; LA32-NEXT:    add.w $a0, $a3, $a0
288; LA32-NEXT:    srli.w $a2, $a0, 4
289; LA32-NEXT:    add.w $a0, $a0, $a2
290; LA32-NEXT:    and $a0, $a0, $a4
291; LA32-NEXT:    mul.w $a0, $a0, $a5
292; LA32-NEXT:    srli.w $a0, $a0, 24
293; LA32-NEXT:    add.w $a0, $a0, $a1
294; LA32-NEXT:    move $a1, $zero
295; LA32-NEXT:    ret
296;
297; LA64-LABEL: test_ctpop_i64:
298; LA64:       # %bb.0:
299; LA64-NEXT:    vldi $vr0, 0
300; LA64-NEXT:    vinsgr2vr.d $vr0, $a0, 0
301; LA64-NEXT:    vpcnt.d $vr0, $vr0
302; LA64-NEXT:    vpickve2gr.d $a0, $vr0, 0
303; LA64-NEXT:    ret
304  %1 = call i64 @llvm.ctpop.i64(i64 %a)
305  ret i64 %1
306}
307
308define i8 @test_cttz_i8(i8 %a) nounwind {
309; LA32-LABEL: test_cttz_i8:
310; LA32:       # %bb.0:
311; LA32-NEXT:    ori $a0, $a0, 256
312; LA32-NEXT:    ctz.w $a0, $a0
313; LA32-NEXT:    ret
314;
315; LA64-LABEL: test_cttz_i8:
316; LA64:       # %bb.0:
317; LA64-NEXT:    ori $a0, $a0, 256
318; LA64-NEXT:    ctz.d $a0, $a0
319; LA64-NEXT:    ret
320  %tmp = call i8 @llvm.cttz.i8(i8 %a, i1 false)
321  ret i8 %tmp
322}
323
324define i16 @test_cttz_i16(i16 %a) nounwind {
325; LA32-LABEL: test_cttz_i16:
326; LA32:       # %bb.0:
327; LA32-NEXT:    lu12i.w $a1, 16
328; LA32-NEXT:    or $a0, $a0, $a1
329; LA32-NEXT:    ctz.w $a0, $a0
330; LA32-NEXT:    ret
331;
332; LA64-LABEL: test_cttz_i16:
333; LA64:       # %bb.0:
334; LA64-NEXT:    lu12i.w $a1, 16
335; LA64-NEXT:    or $a0, $a0, $a1
336; LA64-NEXT:    ctz.d $a0, $a0
337; LA64-NEXT:    ret
338  %tmp = call i16 @llvm.cttz.i16(i16 %a, i1 false)
339  ret i16 %tmp
340}
341
342define i32 @test_cttz_i32(i32 %a) nounwind {
343; LA32-LABEL: test_cttz_i32:
344; LA32:       # %bb.0:
345; LA32-NEXT:    ctz.w $a0, $a0
346; LA32-NEXT:    ret
347;
348; LA64-LABEL: test_cttz_i32:
349; LA64:       # %bb.0:
350; LA64-NEXT:    ctz.w $a0, $a0
351; LA64-NEXT:    ret
352  %tmp = call i32 @llvm.cttz.i32(i32 %a, i1 false)
353  ret i32 %tmp
354}
355
356define i64 @test_cttz_i64(i64 %a) nounwind {
357; LA32-LABEL: test_cttz_i64:
358; LA32:       # %bb.0:
359; LA32-NEXT:    sltu $a2, $zero, $a0
360; LA32-NEXT:    ctz.w $a0, $a0
361; LA32-NEXT:    maskeqz $a0, $a0, $a2
362; LA32-NEXT:    ctz.w $a1, $a1
363; LA32-NEXT:    addi.w $a1, $a1, 32
364; LA32-NEXT:    masknez $a1, $a1, $a2
365; LA32-NEXT:    or $a0, $a0, $a1
366; LA32-NEXT:    move $a1, $zero
367; LA32-NEXT:    ret
368;
369; LA64-LABEL: test_cttz_i64:
370; LA64:       # %bb.0:
371; LA64-NEXT:    ctz.d $a0, $a0
372; LA64-NEXT:    ret
373  %tmp = call i64 @llvm.cttz.i64(i64 %a, i1 false)
374  ret i64 %tmp
375}
376
377define i8 @test_not_cttz_i8(i8 %a) nounwind {
378; LA32-LABEL: test_not_cttz_i8:
379; LA32:       # %bb.0:
380; LA32-NEXT:    ori $a1, $zero, 256
381; LA32-NEXT:    orn $a0, $a1, $a0
382; LA32-NEXT:    ctz.w $a0, $a0
383; LA32-NEXT:    ret
384;
385; LA64-LABEL: test_not_cttz_i8:
386; LA64:       # %bb.0:
387; LA64-NEXT:    ori $a1, $zero, 256
388; LA64-NEXT:    orn $a0, $a1, $a0
389; LA64-NEXT:    ctz.d $a0, $a0
390; LA64-NEXT:    ret
391  %neg = xor i8 %a, -1
392  %tmp = call i8 @llvm.cttz.i8(i8 %neg, i1 false)
393  ret i8 %tmp
394}
395
396define i16 @test_not_cttz_i16(i16 %a) nounwind {
397; LA32-LABEL: test_not_cttz_i16:
398; LA32:       # %bb.0:
399; LA32-NEXT:    lu12i.w $a1, 16
400; LA32-NEXT:    orn $a0, $a1, $a0
401; LA32-NEXT:    ctz.w $a0, $a0
402; LA32-NEXT:    ret
403;
404; LA64-LABEL: test_not_cttz_i16:
405; LA64:       # %bb.0:
406; LA64-NEXT:    lu12i.w $a1, 16
407; LA64-NEXT:    orn $a0, $a1, $a0
408; LA64-NEXT:    ctz.d $a0, $a0
409; LA64-NEXT:    ret
410  %neg = xor i16 %a, -1
411  %tmp = call i16 @llvm.cttz.i16(i16 %neg, i1 false)
412  ret i16 %tmp
413}
414
415define i32 @test_not_cttz_i32(i32 %a) nounwind {
416; LA32-LABEL: test_not_cttz_i32:
417; LA32:       # %bb.0:
418; LA32-NEXT:    cto.w $a0, $a0
419; LA32-NEXT:    ret
420;
421; LA64-LABEL: test_not_cttz_i32:
422; LA64:       # %bb.0:
423; LA64-NEXT:    cto.w $a0, $a0
424; LA64-NEXT:    ret
425  %neg = xor i32 %a, -1
426  %tmp = call i32 @llvm.cttz.i32(i32 %neg, i1 false)
427  ret i32 %tmp
428}
429
430define i64 @test_not_cttz_i64(i64 %a) nounwind {
431; LA32-LABEL: test_not_cttz_i64:
432; LA32:       # %bb.0:
433; LA32-NEXT:    nor $a2, $a0, $zero
434; LA32-NEXT:    sltu $a2, $zero, $a2
435; LA32-NEXT:    cto.w $a1, $a1
436; LA32-NEXT:    addi.w $a1, $a1, 32
437; LA32-NEXT:    masknez $a1, $a1, $a2
438; LA32-NEXT:    cto.w $a0, $a0
439; LA32-NEXT:    maskeqz $a0, $a0, $a2
440; LA32-NEXT:    or $a0, $a0, $a1
441; LA32-NEXT:    move $a1, $zero
442; LA32-NEXT:    ret
443;
444; LA64-LABEL: test_not_cttz_i64:
445; LA64:       # %bb.0:
446; LA64-NEXT:    cto.d $a0, $a0
447; LA64-NEXT:    ret
448  %neg = xor i64 %a, -1
449  %tmp = call i64 @llvm.cttz.i64(i64 %neg, i1 false)
450  ret i64 %tmp
451}
452