[CodeGenPrepare] Teach when it is profitable to speculate calls to @llvm.cttz/ctlz.
[oota-llvm.git] / test / CodeGen / X86 / cttz-ctlz.ll
1 ; RUN: opt -S -codegenprepare -mtriple=x86_64-unknown-unknown -mattr=+bmi < %s | FileCheck %s --check-prefix=ALL --check-prefix=BMI
2 ; RUN: opt -S -codegenprepare -mtriple=x86_64-unknown-unknown -mattr=+lzcnt < %s | FileCheck %s --check-prefix=ALL --check-prefix=LZCNT
3 ; RUN: opt -S -codegenprepare -mtriple=x86_64-unknown-unknown < %s | FileCheck %s --check-prefix=ALL --check-prefix=GENERIC
4
5
6 define i64 @test1(i64 %A) {
7 ; ALL-LABEL: @test1(
8 ; LZCNT: [[CTLZ:%[A-Za-z0-9]+]] = call i64 @llvm.ctlz.i64(i64 %A, i1 false)
9 ; LZCNT-NEXT: ret i64 [[CTLZ]]
10 ; BMI: icmp eq i64 %A, 0
11 ; BMI: call i64 @llvm.ctlz.i64(i64 %A, i1 true)
12 ; GENERIC: icmp eq i64 %A, 0
13 ; GENERIC: call i64 @llvm.ctlz.i64(i64 %A, i1 true)
14 entry:
15   %tobool = icmp eq i64 %A, 0
16   br i1 %tobool, label %cond.end, label %cond.true
17
18 cond.true:                                        ; preds = %entry
19   %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true)
20   br label %cond.end
21
22 cond.end:                                         ; preds = %entry, %cond.true
23   %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ]
24   ret i64 %cond
25 }
26
27
28 define i32 @test2(i32 %A) {
29 ; ALL-LABEL: @test2(
30 ; LZCNT: [[CTLZ:%[A-Za-z0-9]+]] = call i32 @llvm.ctlz.i32(i32 %A, i1 false)
31 ; LZCNT-NEXT: ret i32 [[CTLZ]]
32 ; BMI: icmp eq i32 %A, 0
33 ; BMI: call i32 @llvm.ctlz.i32(i32 %A, i1 true)
34 ; GENERIC: icmp eq i32 %A, 0
35 ; GENERIC: call i32 @llvm.ctlz.i32(i32 %A, i1 true)
36 entry:
37   %tobool = icmp eq i32 %A, 0
38   br i1 %tobool, label %cond.end, label %cond.true
39
40 cond.true:                                        ; preds = %entry
41   %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
42   br label %cond.end
43
44 cond.end:                                         ; preds = %entry, %cond.true
45   %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
46   ret i32 %cond
47 }
48
49
50 define signext i16 @test3(i16 signext %A) {
51 ; ALL-LABEL: @test3(
52 ; LZCNT: [[CTLZ:%[A-Za-z0-9]+]] = call i16 @llvm.ctlz.i16(i16 %A, i1 false)
53 ; LZCNT-NEXT: ret i16 [[CTLZ]]
54 ; BMI: icmp eq i16 %A, 0
55 ; BMI: call i16 @llvm.ctlz.i16(i16 %A, i1 true)
56 ; GENERIC: icmp eq i16 %A, 0
57 ; GENERIC: call i16 @llvm.ctlz.i16(i16 %A, i1 true)
58 entry:
59   %tobool = icmp eq i16 %A, 0
60   br i1 %tobool, label %cond.end, label %cond.true
61
62 cond.true:                                        ; preds = %entry
63   %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true)
64   br label %cond.end
65
66 cond.end:                                         ; preds = %entry, %cond.true
67   %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ]
68   ret i16 %cond
69 }
70
71
72 define i64 @test1b(i64 %A) {
73 ; ALL-LABEL: @test1b(
74 ; LZCNT: icmp eq i64 %A, 0
75 ; LZCNT: call i64 @llvm.cttz.i64(i64 %A, i1 true)
76 ; BMI: [[CTTZ:%[A-Za-z0-9]+]] = call i64 @llvm.cttz.i64(i64 %A, i1 false)
77 ; BMI-NEXT: ret i64 [[CTTZ]]
78 ; GENERIC: icmp eq i64 %A, 0
79 ; GENERIC: call i64 @llvm.cttz.i64(i64 %A, i1 true)
80 entry:
81   %tobool = icmp eq i64 %A, 0
82   br i1 %tobool, label %cond.end, label %cond.true
83
84 cond.true:                                        ; preds = %entry
85   %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true)
86   br label %cond.end
87
88 cond.end:                                         ; preds = %entry, %cond.true
89   %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ]
90   ret i64 %cond
91 }
92
93
94 define i32 @test2b(i32 %A) {
95 ; ALL-LABEL: @test2b(
96 ; LZCNT: icmp eq i32 %A, 0
97 ; LZCNT: call i32 @llvm.cttz.i32(i32 %A, i1 true)
98 ; BMI: [[CTTZ:%[A-Za-z0-9]+]] = call i32 @llvm.cttz.i32(i32 %A, i1 false)
99 ; BMI-NEXT: ret i32 [[CTTZ]]
100 ; GENERIC: icmp eq i32 %A, 0
101 ; GENERIC: call i32 @llvm.cttz.i32(i32 %A, i1 true)
102 entry:
103   %tobool = icmp eq i32 %A, 0
104   br i1 %tobool, label %cond.end, label %cond.true
105
106 cond.true:                                        ; preds = %entry
107   %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
108   br label %cond.end
109
110 cond.end:                                         ; preds = %entry, %cond.true
111   %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
112   ret i32 %cond
113 }
114
115
116 define signext i16 @test3b(i16 signext %A) {
117 ; ALL-LABEL: @test3b(
118 ; LZCNT: icmp eq i16 %A, 0
119 ; LZCNT: call i16 @llvm.cttz.i16(i16 %A, i1 true)
120 ; BMI: [[CTTZ:%[A-Za-z0-9]+]] = call i16 @llvm.cttz.i16(i16 %A, i1 false)
121 ; BMI-NEXT: ret i16 [[CTTZ]]
122 ; GENERIC: icmp eq i16 %A, 0
123 ; GENERIC: call i16 @llvm.cttz.i16(i16 %A, i1 true)
124 entry:
125   %tobool = icmp eq i16 %A, 0
126   br i1 %tobool, label %cond.end, label %cond.true
127
128 cond.true:                                        ; preds = %entry
129   %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true)
130   br label %cond.end
131
132 cond.end:                                         ; preds = %entry, %cond.true
133   %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ]
134   ret i16 %cond
135 }
136
137
138 define i64 @test1c(i64 %A) {
139 ; ALL-LABEL: @test1c(
140 ; ALL: icmp eq i64 %A, 0
141 ; ALL: call i64 @llvm.ctlz.i64(i64 %A, i1 true)
142 entry:
143   %tobool = icmp eq i64 %A, 0
144   br i1 %tobool, label %cond.end, label %cond.true
145
146 cond.true:                                        ; preds = %entry
147   %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true)
148   br label %cond.end
149
150 cond.end:                                         ; preds = %entry, %cond.true
151   %cond = phi i64 [ %0, %cond.true ], [ 63, %entry ]
152   ret i64 %cond
153 }
154
155 define i32 @test2c(i32 %A) {
156 ; ALL-LABEL: @test2c(
157 ; ALL: icmp eq i32 %A, 0
158 ; ALL: call i32 @llvm.ctlz.i32(i32 %A, i1 true)
159 entry:
160   %tobool = icmp eq i32 %A, 0
161   br i1 %tobool, label %cond.end, label %cond.true
162
163 cond.true:                                        ; preds = %entry
164   %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
165   br label %cond.end
166
167 cond.end:                                         ; preds = %entry, %cond.true
168   %cond = phi i32 [ %0, %cond.true ], [ 31, %entry ]
169   ret i32 %cond
170 }
171
172
173 define signext i16 @test3c(i16 signext %A) {
174 ; ALL-LABEL: @test3c(
175 ; ALL: icmp eq i16 %A, 0
176 ; ALL: call i16 @llvm.ctlz.i16(i16 %A, i1 true)
177 entry:
178   %tobool = icmp eq i16 %A, 0
179   br i1 %tobool, label %cond.end, label %cond.true
180
181 cond.true:                                        ; preds = %entry
182   %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true)
183   br label %cond.end
184
185 cond.end:                                         ; preds = %entry, %cond.true
186   %cond = phi i16 [ %0, %cond.true ], [ 15, %entry ]
187   ret i16 %cond
188 }
189
190
191 define i64 @test1d(i64 %A) {
192 ; ALL-LABEL: @test1d(
193 ; ALL: icmp eq i64 %A, 0
194 ; ALL: call i64 @llvm.cttz.i64(i64 %A, i1 true)
195 entry:
196   %tobool = icmp eq i64 %A, 0
197   br i1 %tobool, label %cond.end, label %cond.true
198
199 cond.true:                                        ; preds = %entry
200   %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true)
201   br label %cond.end
202
203 cond.end:                                         ; preds = %entry, %cond.true
204   %cond = phi i64 [ %0, %cond.true ], [ 63, %entry ]
205   ret i64 %cond
206 }
207
208
209 define i32 @test2d(i32 %A) {
210 ; ALL-LABEL: @test2d(
211 ; ALL: icmp eq i32 %A, 0
212 ; ALL: call i32 @llvm.cttz.i32(i32 %A, i1 true)
213 entry:
214   %tobool = icmp eq i32 %A, 0
215   br i1 %tobool, label %cond.end, label %cond.true
216
217 cond.true:                                        ; preds = %entry
218   %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
219   br label %cond.end
220
221 cond.end:                                         ; preds = %entry, %cond.true
222   %cond = phi i32 [ %0, %cond.true ], [ 31, %entry ]
223   ret i32 %cond
224 }
225
226
227 define signext i16 @test3d(i16 signext %A) {
228 ; ALL-LABEL: @test3d(
229 ; ALL: icmp eq i16 %A, 0
230 ; ALL: call i16 @llvm.cttz.i16(i16 %A, i1 true)
231 entry:
232   %tobool = icmp eq i16 %A, 0
233   br i1 %tobool, label %cond.end, label %cond.true
234
235 cond.true:                                        ; preds = %entry
236   %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true)
237   br label %cond.end
238
239 cond.end:                                         ; preds = %entry, %cond.true
240   %cond = phi i16 [ %0, %cond.true ], [ 15, %entry ]
241   ret i16 %cond
242 }
243
244
245 declare i64 @llvm.ctlz.i64(i64, i1)
246 declare i32 @llvm.ctlz.i32(i32, i1)
247 declare i16 @llvm.ctlz.i16(i16, i1)
248 declare i64 @llvm.cttz.i64(i64, i1)
249 declare i32 @llvm.cttz.i32(i32, i1)
250 declare i16 @llvm.cttz.i16(i16, i1)