1; RUN: llc < %s -march=x86-64 -mcpu=yonah | FileCheck %s
2
3declare i8 @llvm.cttz.i8(i8, i1)
4declare i16 @llvm.cttz.i16(i16, i1)
5declare i32 @llvm.cttz.i32(i32, i1)
6declare i64 @llvm.cttz.i64(i64, i1)
7declare i8 @llvm.ctlz.i8(i8, i1)
8declare i16 @llvm.ctlz.i16(i16, i1)
9declare i32 @llvm.ctlz.i32(i32, i1)
10declare i64 @llvm.ctlz.i64(i64, i1)
11
12define i8 @cttz_i8(i8 %x)  {
13  %tmp = call i8 @llvm.cttz.i8( i8 %x, i1 true )
14  ret i8 %tmp
15; CHECK-LABEL: cttz_i8:
16; CHECK: bsfl
17; CHECK-NOT: cmov
18; CHECK: ret
19}
20
21define i16 @cttz_i16(i16 %x)  {
22  %tmp = call i16 @llvm.cttz.i16( i16 %x, i1 true )
23  ret i16 %tmp
24; CHECK-LABEL: cttz_i16:
25; CHECK: bsfw
26; CHECK-NOT: cmov
27; CHECK: ret
28}
29
30define i32 @cttz_i32(i32 %x)  {
31  %tmp = call i32 @llvm.cttz.i32( i32 %x, i1 true )
32  ret i32 %tmp
33; CHECK-LABEL: cttz_i32:
34; CHECK: bsfl
35; CHECK-NOT: cmov
36; CHECK: ret
37}
38
39define i64 @cttz_i64(i64 %x)  {
40  %tmp = call i64 @llvm.cttz.i64( i64 %x, i1 true )
41  ret i64 %tmp
42; CHECK-LABEL: cttz_i64:
43; CHECK: bsfq
44; CHECK-NOT: cmov
45; CHECK: ret
46}
47
48define i8 @ctlz_i8(i8 %x) {
49entry:
50  %tmp2 = call i8 @llvm.ctlz.i8( i8 %x, i1 true )
51  ret i8 %tmp2
52; CHECK-LABEL: ctlz_i8:
53; CHECK: bsrl
54; CHECK-NOT: cmov
55; CHECK: xorl $7,
56; CHECK: ret
57}
58
59define i16 @ctlz_i16(i16 %x) {
60entry:
61  %tmp2 = call i16 @llvm.ctlz.i16( i16 %x, i1 true )
62  ret i16 %tmp2
63; CHECK-LABEL: ctlz_i16:
64; CHECK: bsrw
65; CHECK-NOT: cmov
66; CHECK: xorl $15,
67; CHECK: ret
68}
69
70define i32 @ctlz_i32(i32 %x) {
71  %tmp = call i32 @llvm.ctlz.i32( i32 %x, i1 true )
72  ret i32 %tmp
73; CHECK-LABEL: ctlz_i32:
74; CHECK: bsrl
75; CHECK-NOT: cmov
76; CHECK: xorl $31,
77; CHECK: ret
78}
79
80define i64 @ctlz_i64(i64 %x) {
81  %tmp = call i64 @llvm.ctlz.i64( i64 %x, i1 true )
82  ret i64 %tmp
83; CHECK-LABEL: ctlz_i64:
84; CHECK: bsrq
85; CHECK-NOT: cmov
86; CHECK: xorq $63,
87; CHECK: ret
88}
89
90define i32 @ctlz_i32_cmov(i32 %n) {
91entry:
92; Generate a cmov to handle zero inputs when necessary.
93; CHECK-LABEL: ctlz_i32_cmov:
94; CHECK: bsrl
95; CHECK: cmov
96; CHECK: xorl $31,
97; CHECK: ret
98  %tmp1 = call i32 @llvm.ctlz.i32(i32 %n, i1 false)
99  ret i32 %tmp1
100}
101
102define i32 @ctlz_i32_fold_cmov(i32 %n) {
103entry:
104; Don't generate the cmovne when the source is known non-zero (and bsr would
105; not set ZF).
106; rdar://9490949
107; CHECK-LABEL: ctlz_i32_fold_cmov:
108; CHECK: bsrl
109; CHECK-NOT: cmov
110; CHECK: xorl $31,
111; CHECK: ret
112  %or = or i32 %n, 1
113  %tmp1 = call i32 @llvm.ctlz.i32(i32 %or, i1 false)
114  ret i32 %tmp1
115}
116
117define i32 @ctlz_bsr(i32 %n) {
118entry:
119; Don't generate any xors when a 'ctlz' intrinsic is actually used to compute
120; the most significant bit, which is what 'bsr' does natively.
121; CHECK-LABEL: ctlz_bsr:
122; CHECK: bsrl
123; CHECK-NOT: xorl
124; CHECK: ret
125  %ctlz = call i32 @llvm.ctlz.i32(i32 %n, i1 true)
126  %bsr = xor i32 %ctlz, 31
127  ret i32 %bsr
128}
129
130define i32 @ctlz_bsr_cmov(i32 %n) {
131entry:
132; Same as ctlz_bsr, but ensure this happens even when there is a potential
133; zero.
134; CHECK-LABEL: ctlz_bsr_cmov:
135; CHECK: bsrl
136; CHECK-NOT: xorl
137; CHECK: ret
138  %ctlz = call i32 @llvm.ctlz.i32(i32 %n, i1 false)
139  %bsr = xor i32 %ctlz, 31
140  ret i32 %bsr
141}
142